Sgu 103
容易想到,对于某个顶点,先到达总不会比后到达要差,因此本题可用贪心算法,联系图论中的最短路求法,本题可采用dijkstra算法,难点主要在边权的计算上,详见windywinter牛的题解: http://www.briefdream.com/sgu-103/。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 struct news
5 {
6 int r,tb,tp,c;
7 } juc[301];
8 struct color
9 {
10 int c,t;
11 };
12 int map[301][301],dis[301],pre[301],start,end,n,m;
13 bool reach[301];
14 int ans[301],ansnum;
15 int min(int a, int b)
16 {
17 return a>b?b:a;
18 }
19 void init()
20 {
21 scanf("%d %d\n%d %d\n",&start,&end,&n,&m);
22 for(int i=1;i<=n;++i)
23 {
24 char tmp;
25 scanf("%c %d %d %d\n",&tmp,&juc[i].r,&juc[i].tb,&juc[i].tp);
26 juc[i].c=tmp=='B'?0:1;
27 }
28 for(int i=1;i<=m;++i)
29 {
30 int x,y,z;
31 scanf("%d %d %d",&x,&y,&z);
32 map[x][y]=map[y][x]=z;
33 }
34 }
35 color calccolor(int id, int nowtime)
36 {
37 color ans;
38 int r=juc[id].r,tb=juc[id].tb,tp=juc[id].tp;
39 if(nowtime<r)
40 {
41 ans.c=juc[id].c;
42 ans.t=r-nowtime;
43 }
44 else if(!juc[id].c)
45 {
46 if(ans.c=(nowtime-r)%(tb+tp)<tp)
47 ans.t=tp-(nowtime-r)%(tb+tp);
48 else
49 ans.t=tb+tp-(nowtime-r)%(tb+tp);
50 }
51 else
52 {
53 if(ans.c=(nowtime-r)%(tb+tp)>=tb)
54 ans.t=tb+tp-(nowtime-r)%(tb+tp);
55 else
56 ans.t=tb-(nowtime-r)%(tb+tp);
57 }
58 return ans;
59 }
60 int calc(int starttime, int fromid, int toid, int flag)
61 {
62 if(flag>3) return -1;
63 color from,to;
64 from=calccolor(fromid,starttime);
65 to=calccolor(toid,starttime);
66 if(from.c==to.c) return starttime;
67 if(from.t==to.t) return calc(starttime+from.t,fromid,toid,flag+1);
68 return starttime+min(from.t,to.t);
69 }
70 void work()// dijkstra
71 {
72 bool vis[301]={false};
73 memset(dis,0x77,sizeof(dis));
74 dis[start]=0;
75 pre[start]=-1;
76 reach[start]=true;
77 int leftnum=n;
78 while(leftnum)
79 {
80 int mindis=99999999,now;
81 for(int i=1;i<=n;++i) if(!vis[i])
82 if(dis[i]<mindis)
83 {
84 now=i;
85 mindis=dis[i];
86 }
87 --leftnum;
88 vis[now]=true;
89 for(int i=1;i<=n;++i) if(map[now][i])
90 {
91 int tmp=calc(dis[now],now,i,1);
92 if(tmp==-1) continue;
93 tmp+=map[now][i];
94 if(tmp<dis[i])
95 {
96 dis[i]=tmp;
97 pre[i]=now;
98 reach[i]=true;
99 }
100 }
101 }
102 }
103 void print()
104 {
105 if(!reach[end])
106 {
107 printf("0\n");
108 return;
109 }
110 printf("%d\n",dis[end]);
111 int now=end;
112 while(now!=-1)
113 {
114 ans[++ansnum]=now;
115 now=pre[now];
116 }
117 printf("%d",ans[ansnum]);
118 for(int i=ansnum-1;i>=1;--i)
119 printf(" %d",ans[i]);
120 printf("\n");
121 }
122 int main()
123 {
124 init();
125 work();
126 print();
127 return 0;
128 }
2 #include<stdlib.h>
3 #include<string.h>
4 struct news
5 {
6 int r,tb,tp,c;
7 } juc[301];
8 struct color
9 {
10 int c,t;
11 };
12 int map[301][301],dis[301],pre[301],start,end,n,m;
13 bool reach[301];
14 int ans[301],ansnum;
15 int min(int a, int b)
16 {
17 return a>b?b:a;
18 }
19 void init()
20 {
21 scanf("%d %d\n%d %d\n",&start,&end,&n,&m);
22 for(int i=1;i<=n;++i)
23 {
24 char tmp;
25 scanf("%c %d %d %d\n",&tmp,&juc[i].r,&juc[i].tb,&juc[i].tp);
26 juc[i].c=tmp=='B'?0:1;
27 }
28 for(int i=1;i<=m;++i)
29 {
30 int x,y,z;
31 scanf("%d %d %d",&x,&y,&z);
32 map[x][y]=map[y][x]=z;
33 }
34 }
35 color calccolor(int id, int nowtime)
36 {
37 color ans;
38 int r=juc[id].r,tb=juc[id].tb,tp=juc[id].tp;
39 if(nowtime<r)
40 {
41 ans.c=juc[id].c;
42 ans.t=r-nowtime;
43 }
44 else if(!juc[id].c)
45 {
46 if(ans.c=(nowtime-r)%(tb+tp)<tp)
47 ans.t=tp-(nowtime-r)%(tb+tp);
48 else
49 ans.t=tb+tp-(nowtime-r)%(tb+tp);
50 }
51 else
52 {
53 if(ans.c=(nowtime-r)%(tb+tp)>=tb)
54 ans.t=tb+tp-(nowtime-r)%(tb+tp);
55 else
56 ans.t=tb-(nowtime-r)%(tb+tp);
57 }
58 return ans;
59 }
60 int calc(int starttime, int fromid, int toid, int flag)
61 {
62 if(flag>3) return -1;
63 color from,to;
64 from=calccolor(fromid,starttime);
65 to=calccolor(toid,starttime);
66 if(from.c==to.c) return starttime;
67 if(from.t==to.t) return calc(starttime+from.t,fromid,toid,flag+1);
68 return starttime+min(from.t,to.t);
69 }
70 void work()// dijkstra
71 {
72 bool vis[301]={false};
73 memset(dis,0x77,sizeof(dis));
74 dis[start]=0;
75 pre[start]=-1;
76 reach[start]=true;
77 int leftnum=n;
78 while(leftnum)
79 {
80 int mindis=99999999,now;
81 for(int i=1;i<=n;++i) if(!vis[i])
82 if(dis[i]<mindis)
83 {
84 now=i;
85 mindis=dis[i];
86 }
87 --leftnum;
88 vis[now]=true;
89 for(int i=1;i<=n;++i) if(map[now][i])
90 {
91 int tmp=calc(dis[now],now,i,1);
92 if(tmp==-1) continue;
93 tmp+=map[now][i];
94 if(tmp<dis[i])
95 {
96 dis[i]=tmp;
97 pre[i]=now;
98 reach[i]=true;
99 }
100 }
101 }
102 }
103 void print()
104 {
105 if(!reach[end])
106 {
107 printf("0\n");
108 return;
109 }
110 printf("%d\n",dis[end]);
111 int now=end;
112 while(now!=-1)
113 {
114 ans[++ansnum]=now;
115 now=pre[now];
116 }
117 printf("%d",ans[ansnum]);
118 for(int i=ansnum-1;i>=1;--i)
119 printf(" %d",ans[i]);
120 printf("\n");
121 }
122 int main()
123 {
124 init();
125 work();
126 print();
127 return 0;
128 }