最短路径问题 Dijkstra
题意:
有n个关键骨牌,每两个关键骨牌之间之多有一行普通骨牌,一共有m行骨牌,可以理解成有m条边。从第一张骨牌开始推到,最后一张倒下的骨牌要么是关键骨牌,要么是两张关键骨牌中的一张。
分析:
先用Dijkstra算法求出每张关键牌的最短路径,然后计算每一行倒下的时间,记录关键牌倒下的时间和位置,枚举每一行中间的普通牌倒下的时间和两端的关键牌位置。
这道题警醒我,英语学得不够好!做题看题目不够细心!在POJ上面 WA 8次,换来血的教训!!
WA的原因有以下几点:
1)
if(maxt2 > maxt1) printf("%.1f seconds, and key domino %d and %d.\n\n",maxt2, pos1+1, pos2+1);
if(maxt2 > maxt1) printf("%.1f seconds, between key domino %d and %d.\n\n",maxt2, pos1+1, pos2+1);
if(maxt2 > maxt1) printf("%.1f seconds, between key dominos %d and %d.\n\n",maxt2, pos1+1, pos2+1);
下面放上第九次提交终于血泪中AC的代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define MAXN 510 #define INF 1000000 int n,m; double maxt1,maxt2; int pos,pos1,pos2,i,j,k; int _time[MAXN],e[MAXN][MAXN],s[MAXN]; void Solve( ) { memset(s, 0, sizeof(s)); memset(_time, 0, sizeof(_time)); for(i=0; i<n; i++) { _time[i] = e[0][i]; } _time[0] = 0; s[0] = 1; for(i=1; i<n; i++) { int min = INF; int u = 0; for(j=0; j<n; j++) { if(!s[j] && _time[j]<min) { u = j; min = _time[j]; } } s[u] = 1; for(k=0; k<n; k++) { if(!s[k] && e[u][k]<INF && _time[u]+e[k][u]<_time[k]) { _time[k] = _time[u] + e[k][u]; } } } maxt1 = -INF; for(i=0 ;i<n; i++) { if(_time[i] > maxt1) { maxt1 = _time[i]; pos = i; } } double t; maxt2 = -INF; for(i=0; i<n; i++) { for(j=0; j<n; j++) { t = (_time[i] + _time[j] + e[i][j])/2.0; if(e[i][j]<INF && t>maxt2) { maxt2 = t; pos1 = i; pos2 = j; } } } } int main( ) { int a, b, t, Case = 1; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0 && m==0) break; for(i=0; i<n; i++) for(j=0; j<n; j++) { e[i][j] = INF; } for(i=0; i<m; i++) { scanf("%d%d%d",&a,&b,&t); a--; b--; e[a][b] = e[b][a] = t; } Solve(); printf("System #%d\n", Case++); printf("The last domino falls after "); if(maxt2 > maxt1) printf("%.1f seconds, between key dominoes %d and %d.\n\n", maxt2, pos1+1, pos2+1); else printf("%.1f seconds, at key domino %d.\n\n", maxt1, pos+1); } return 0; }