POJ 1797

116 篇文章 2 订阅
7 篇文章 0 订阅

题目咋一看,就是 最短路问题,解法是  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)),把参数作为一个整体。


我在做这道题的时候, 算法方面没什么问题,但是一些小的细节 困了我好久,每次调试 都 感觉好烦。但 渐渐的,我发现,只有自己亲手写代码,调试,发现错误,水平才会提高。照着别人代码写,很多问题 和 细节 都会 被略去。 所以,我建议,可以借鉴别人的思想,但 代码一定要自己敲,自己还原算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值