题目咋一看,就是 最短路问题,解法是 Dijkstra 算法的变体。
题目大意是 给定n个城市,和 它们之间的 m 条街道,以及街道上的 最大载重。 可以这样理解,现在找一辆车从 城市 1 到往 城市 n,求最大的载重,前提是 不能把 街道压坏,也就是载重必须小于等于 给定的街道最大载重。
这里只需要 将 Dijkstra 算法里面的 更新边的条件 改一下,也就是 d[i] 表示1城市到 i 城市 可以承受的最大载重,先找到 d[] 的最大值,然后根据 是否min(d[k],map[k][j]) 大于 d[j],来更新 d[] 数组。
#include <iostream> using namespace std; //#define min(a,b) ((a)<(b)?(a):(b)) #define min(a,b) (a<b?a:b) #define MAXN 1010 int map[MAXN][MAXN]; bool vis[MAXN]; int d[MAXN]; int n; //表示n个城市 int dijkstra(){ int i,j,k,temp; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) d[i] = map[1][i]; for(i=1;i<=n;i++){ temp = -1; k = 0; for(j=1;j<=n;j++){ if(!vis[j]&&d[j]>temp){ temp = d[j]; k = j; } } vis[k] = 1; for(j=1;j<=n;j++){ if(!vis[j]&&d[j]<min(d[k],map[k][j])){ d[j] = min(d[k],map[k][j]); } } } return d[n]; } int main(){ int plans; cin>>plans; int m,i,j; int v1,v2,v3; int index = 1; while(plans--){ cin>>n>>m; for(i=0;i<=n;i++) for(j=0;j<=n;j++) map[i][j] = 0; for(i=1;i<=m;i++){ cin>>v1>>v2>>v3; map[v1][v2] = map[v2][v1] = v3; } cout<<"Scenario #"<<index++<<":"<<endl; cout<<dijkstra()<<endl; cout<<endl; } return 0; }
首先,index的值,每次output之后 都要自增;第二,每次output之后,都要换行(题目中有写)。。
第三,在 Dijkstra 算法里面,求d[] 最大值时,注意不能在初始状态把 temp = d[1], k = 1,这样写的话,会导致后面 相同值的标号 无法计算到,若d[1] = d[2],那么 k 就永远等于2了。
第四,也是最重要的 一点,那就是 预定义函数了,这个调试了 我好久。
#define min(a,b) ((a)<(b)?(a):(b)) 或者写成 #define min(a,b) (a<b?a:b) , 对于这道题 都可以。
不过我还是建议 用前一种,比较保险,因为用 define 预定义函数,必须要将 参数 都加括号。
至于为什么,我举一个经典的例子:
#define function(a) a*a
调用的时候 function(2+2) 就会 出错,应该是16, 它输出8,这里把括号扩在外面都没用,要((a)*(a)),把参数作为一个整体。
我在做这道题的时候, 算法方面没什么问题,但是一些小的细节 困了我好久,每次调试 都 感觉好烦。但 渐渐的,我发现,只有自己亲手写代码,调试,发现错误,水平才会提高。照着别人代码写,很多问题 和 细节 都会 被略去。 所以,我建议,可以借鉴别人的思想,但 代码一定要自己敲,自己还原算法。