103. Traffic Lights

Time limit per test: 0.25 second(s)

Memory limit: 4096 kilobytes

题解:

1、其实就是求两点间的最短路,不过加了交通灯的限制,使得两点间的所需时间并不只是由路程决定。

2、只有一条路两个端点的交通灯颜色相同时,该路才可以通过。但是这有一种情况,当两个交通灯处于不同颜色时,经过t时间,交通灯又恰好处于不同颜色,由于最初有一个颜色预变时间riC以及蓝色tiB、紫色周期tiP ,那么就需要计算交通灯变化时间的函数递归两次(函数执行三次),如果递归两次后还处于不同颜色,那么可以断定该交通灯蓝、紫色周期相反,不能通过。例如B 32 32 13和P 32 96 49 经过32s后变成P 13 32 13 和B 96 96 49(紫色变为蓝色后,将过tiB时间即96变为紫色),那么很显然,此时再过13s即可变为相同颜色。那么这两点所需等待交通灯时间为13+32=45s。一开始只都递归了一次,在test 6的时候挂了,所以计算等待函数,应递归两次。

3、最短路算法,dijkstra算法的复杂度为O(N^2),最后提交的结果是用时31ms。当然求最短路,dfs也是可以的,但是经过尝试,dfs在test 2 就TLE了。

以下是代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdlib>
using namespace std;
int st,ed;
int N,M;
int c[2][2]; //0 b,1 p;
int a[310][310]; // 记录输入的无向图
int Min=INT_MAX; // 最大值
struct Light{ // 记录输入的交通灯的信息
int c, t,b,p;// c输入的颜色,t变换时间,b,p周期
}L[310];
void input(){ // 输入
int t1,t2;
char str[3];
scanf("%d%d%d%d",&st,&ed,&N,&M);
for(int i=1;i<=N;i++){
scanf("%s%d%d%d",str,&L[i].t,&L[i].b,&L[i].p);
L[i].c= str[0] =='B'? 0 :1;
}
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(i!=j)a[i][j]=Min;
for(int i=1;i<=M;i++){
scanf("%d%d",&t1,&t2);
scanf("%d",&a[t1][t2]);
a[t2][t1]=a[t1][t2];
}
}
void calnow(int v,int pre,int k){ //计算第v个节点在过了pre时间后的颜色
if(pre<L[v].t){
c[k][0] = L[v].c;
c[k][1] = L[v].t-pre;
return ;
}
int mo = (pre - L[v].t)%(L[v].b+L[v].p);
switch(L[v].c){
case 0 :
if(mo < L[v].p){
c[k][0]=1;c[k][1]=L[v].p - mo;
}else{
c[k][0]=0;c[k][1]=L[v].b - (mo - L[v].p);
}break;
case 1 :
if(mo < L[v].b){
c[k][0]=0;c[k][1]=L[v].b - mo;
}else{
c[k][0]=1;c[k][1]=L[v].p - (mo - L[v].b);
}break;
}
}
int caldelay(int v,int u,int pre,int f){ // 计算如果走v—u需要多长时间
calnow(v,pre,0);
calnow(u,pre,1);
if(c[0][0] == c[1][0])return 0;
int t1 = c[0][1],t2=c[1][1];
if(t1 == t2){
if(f==2)return -1;else {
int t = caldelay(v,u,pre+t1,f+1);//递归两次,才能确定能否通行。
if(t==-1)return -1;
return t+t1;
}
}
return t1<t2 ? t1:t2;
}
void dijkstra()// 狄杰斯特拉算法,求最短路
{
int v=st;
int d[310],pr[310],vis[310];
memset(vis,0,sizeof(vis));
memset(pr,0,sizeof(pr));
for(int i=0;i<310;i++)d[i]=Min;
for(int i=1;i<=N;i++)
if(a[v][i]<Min){
d[i]=a[v][i]+caldelay(v,i,0,0);
pr[i]= v;
}else{ d[i]=Min;pr[i]=0;}
vis[v]=1;pr[v]=0;
for(int i=1;i<=N;i++){
int k=0,m=Min;
for(int j=1;j<=N;j++)
if(!vis[j] && d[j]< m)m = d[k=j];
if(k==0)break;
vis[k]=1;
for(int j=1;j<=N;j++)
if(k!=j && a[k][j]!=Min){
int t = caldelay(k,j,d[k],0);
if(t==-1)continue;
if(d[j]>d[k]+t+a[k][j]){
d[j] = d[k]+t+a[k][j];
pr[j]=k;
}
}
}
if(st==ed)printf("0\n%d\n",st);
else if(d[ed]==Min)printf("0\n");
else{
printf("%d\n",d[ed]);
int t =ed,path[310],k=0;
while(pr[t]){ path[++k]=pr[t];t =pr[t];}
path[0]=ed;
for(int i=k;i>=0;i--)
printf("%d ",path[i]);
printf("\n");
}
}
int main(){
//freopen("1.in","r",stdin);
input();
dijkstra();
}

以下是测试数据:

sample input

10 2

17 2

B 42 5 96

B 47 51 60

B 49 28 70

B 71 77 17

P 95 97 59

B 5 56 99

B 82 56 74

P 97 60 15

P 78 32 54

B 3 20 55

B 84 8 46

P 93 32 64

B 25 11 99

B 73 33 15

B 59 58 70

P 85 61 61

P 53 13 43

6 12 17

15 12 75

4 4

13 11

P 79 49 75

B 87 71 22

B 11 79 30

P 91 1 72

B 50 59 84

B 88 72 41

B 85 21 47

B 66 11 100

B 39 21 28

B 42 59 42

P 4 47 2

B 41 36 48

P 97 60 25

11 3 38

10 10 57

7 6 86

5 9 69

7 9 17

5 9 77

4 10 13

6 3 79

2 8 78

3 12 90

13 9 37

4 5

5 20

P 35 52 3

B 10 82 91

B 29 81 35

P 85 62 64

B 87 27 12

3 5 39

3 4 98

5 3 19

4 2 4

5 1 36

4 1 94

4 2 12

3 4 41

5 2 90

4 2 2

3 1 71

3 1 33

5 1 94

1 5 67

1 4 65

4 1 54

4 5 16

3 3 22

1 2 19

2 5 76

1 3

4 17

B 73 40 10

P 38 5 50

B 46 64 69

P 93 88 94

1 3 91

3 4 72

2 3 14

4 3 46

3 2 5

2 2 52

2 3 26

1 3 93

1 1 75

4 4 84

4 1 39

2 3 63

3 2 10

4 1 70

1 1 71

2 4 75

1 2 34

sample output

0

0

4

71

4 2 1 5

77

1 2 3

sgu 103 Traffic Lights 解题报告及测试数据的更多相关文章

  1. sgu 103 Traffic Lights

    这道题难得不是算法,而是处理. 题意就是让你求最短路,只有当两个点在某一秒颜色相同时,这条边才可以通行,输入首先给你 起点和终点, 然后给你 点数和边数, 接下来 n 行 初始颜色,初始颜色持续时间, ...

  2. SGU 103.Traffic Lights(最短路)

    时间: 0.50 second(s) 空间: 4096 kilobytes 输入: 标准输入 输出: 标准输出 Dingiville 城市的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多 ...

  3. sgu 100 A+B 解题报告及测试数据

    100.A+B time limit per test: 0.25 sec. memory limit per test: 65536 KB 题解:上手题,不解释. 直接上代码: #include & ...

  4. SGU 103 Traffic Lights【最短路】

    题目链接: http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=16530 题意: 给定每个点最初的颜色,最初颜色持续时间,以 ...

  5. sgu 104 Little shop of flowers 解题报告及测试数据

    104. Little shop of flowers time limit per test: 0.25 sec. memory limit per test: 4096 KB 问题: 你想要将你的 ...

  6. sgu 102 Coprimes 解题报告及测试数据

    102. Coprimes time limit per test: 0.25 sec. memory limit per test: 4096 KB 题解: 求一个1-10000之间的数 N 的互质 ...

  7. sgu 101 Domino 解题报告及测试数据

    101. Domino time limit per test: 0.25 sec. memory limit per test: 4096 KB 题解: 求多米诺骨牌按照一定方式放置能否使相邻的位置 ...

  8. Spring-2-H Array Diversity(SPOJ AMR11H)解题报告及测试数据

    Array Diversity Time Limit:404MS     Memory Limit:0KB     64bit IO Format:%lld & %llu   Descript ...

  9. Winter-2-STL-G Team Queue 解题报告及测试数据

    Time Limit:3000MS     Memory Limit:0KB Description Queues and Priority Queues are data structures wh ...

随机推荐

  1. BEGIN_MESSAGE_MAP(Caccess_test_1Dlg, CDialogEx)

    BEGIN_MESSAGE_MAP(...消息映射宏的一部分.ON_WM_CREATE()产生一个消息处理函数映射项目,把WM_CREATE和OnCreate函数联系起来. 参数的个数和类型是系统已经 ...

  2. AWS系列-S3实现文件服务页面展示

    最近由于业务需求,对于备份的数据存放到S3上面,并需要页面展示.而且还能下载. 把这个桶里面的对象,都在某个静态页面展示.并且 我可以把这个对象下载下来. 首页内容就是 桶里面的对象. 并且可以随时查 ...

  3. A*寻路算法(曼哈顿距离)

    前一些天,在群有人问到A*算法的问题. 之前我已经有实现过,并将之放到github上(https://github.com/XJM2013/A_Star).有兴趣的能够下载下来看看. 这里上传了一个相 ...

  4. 应用开发之WinForm环境

    本章简言 上一章笔者讲到关于IO文件操作类,了解如何处理文件流.从这一章开始笔者将讲解相对比较高级的知识点.而本章笔者就对WinForm开发的知识点进行讲解和引导.现在很多业务都是面向于B/S模式的开 ...

  5. 链接href的多重使用

    1. 拨打电话 在电话号码前面可以加上 + (加号)表示国际号码. <a href="tel:10086">10086</a> 使用wtai协议进行拨打电话 ...

  6. ios学习--结合UIImageView实现图片的移动和缩放

    因为种种原因,需要在iphone应用中实现图片查看功能,由于iphone屏幕支持多点触摸,于是是想到用“手势”来实现图片的实时缩放和移动.借鉴无所不在的internet网络资料之后,终于实现此一功能, ...

  7. 《C#高级编程》学习笔记----c#内存管理--栈VS堆

    本文转载自Netprawn,原文英文版地址 尽管在.net framework中我们不太需要关注内存管理和垃圾回收这方面的问题,但是出于提高我们应用程序性能的目的,在我们的脑子里还是需要有这方面的意识 ...

  8. .net winform 调用类中的webbrowser 报错:当前线程不在单线程单元中,因此无法实例化 ActiveX

    遇到这个恶心的问题纠缠得不要不要的,大家遇到了的话希望不要走弯路,经过这个折腾让我有点怀疑人生了.哈哈哈 解决代码如下: //插入一个新线程用于处理验证码 Thread thd = new Threa ...

  9. linLINUX中常用操作命令

    LINUX中常用操作命令 Linux简介及Ubuntu安装 常见指令 系统管理命令 打包压缩相关命令 关机/重启机器 Linux管道 Linux软件包管理 vim使用 用户及用户组管理 文件权限管理 ...

  10. textarea文本输入区内实现换行

    在文本间输入 即可成功换行 <textarea class="mytextarea">1.第一行 2.第二行 </textarea>