[PAT解题报告] All Roads Lead to Rome

又是最短路,dijkstra算法的变种。
(1) 记录最短路条数, 更新的时候:
用k更新i的时候,有两种情况
如果最短路长度相等,num[i] += num[k]
如果最短路更短 num[i] = num[k]

(2) happiness 和 bypass 这两个没的说,如果要更新的话
happiness[i] = b[i] + happiness[k]
bypass[i] = bypass[k] + 1

所以只是在更新上做手脚,别忘记记录pre[i] = k,以方便倒着还原出路径来。

代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <map>

using namespace std;

const int inf = 1000000000;
const int N = 202;

map<string,int> id;
int cost[N],happy[N],bypass[N],num[N],pre[N],n,a[N][N],b[N];
bool mark[N];    
string name[N];
char s[10];

void dijkstra(int s) {
    for (int i = 0; i < n; ++i) {
        cost[i] = bypass[i] = inf;
        num[i]  = happy[i] = 0;
        mark[i] = false;
    }
    num[s] = 1;
    cost[s] = bypass[s] =  0;
    pre[s] = -1;
    for (int j = 0; j < n; ++j) {
        int k = -1;
        for (int i = 0; i < n; ++i) {
            if ((!mark[i]) && ((k < 0) || (cost[i] < cost[k]))) {
                k = i;
            }
        }
        mark[k] = true;
        for (int i = 0; i < n; ++i) {
            if ((!mark[i]) && (a[k][i] < inf)) {
                int temp = cost[k] + a[k][i];
                if (temp < cost[i]) {
                    cost[i] = temp;
                    happy[i] = happy[k] + b[i];
                    bypass[i] = bypass[k] + 1;
                    num[i] = num[k];
                    pre[i] = k;
                }
                else if (temp == cost[i]) {
                    num[i] += num[k];
                    int mayhappy = happy[k] + b[i];
                    int maybypass = bypass[k] + 1;
                    if ((mayhappy > happy[i]) || ((mayhappy == happy[i]) && (maybypass < bypass[i]))) {
                        happy[i] = mayhappy;
                        bypass[i] = maybypass;
                        pre[i] = k;
                    }
                }
            }
        } 
        
    }
}

void print(int x) {
    if (x) {
        print(pre[x]);
        printf("->");
    }
    printf("%s",name[x].c_str());
}

int main() {
int m;
    scanf("%d%d%s",&n,&m,s);
    id[name[0] = s] = 0;
    b[0] = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            a[i][j] = inf;
        }
    }
    for (int i = 1; i < n; ++i) {
        scanf("%s%d",s,&b[i]);
        id[name[i] = s] = i;
    }
    for (;m;--m) {
        scanf("%s",s);
        int x = id[s];
        scanf("%s",s);
        int y = id[s];
        int z;
        scanf("%d",&z);
        a[x][y] = a[y][x] = min(a[x][y],z);
        
    }
    dijkstra(0);
    int x = id["ROM"];
    printf("%d %d %d %d\n",num[x],cost[x],happy[x],happy[x] / bypass[x]);
    print(x);    
    puts("");
    return 0;
}

原题链接: http://www.patest.cn/contests/pat-a-practise/1087
全部评论
解答不清晰。能否重新修正一下?
点赞 回复 分享
发布于 2015-09-01 07:36
在输入代码中 a[x][y] = a[y][x] = min(a[x][y],z); 这句为啥要写成min(a[x][y],z); 莫非它还会重复输入一条路径而且cost不同???
点赞 回复 分享
发布于 2015-11-04 13:22
#include <stdio.h> #include <map> #include <string> #include <string.h> #include <vector> using namespace std; #define  INF 0xfffffff int n,m; int d[205],w[205][205],hp[205],path[205],l[205],totalhp[205],av_hp[205]; bool vis[205]; map<string,int> mp; string str[205]; int num[205]; void Dj(int s) { int i,j; for(i=0;i<n;i++) if(w[s][i]!=INF) { d[i]=w[s][i],path[i]=s,totalhp[i]=hp[i],l[i]=1,num[i]=1; } else d[i]=INF; d[s]=0; l[s]=0; num[s]=1; vis[s]=true; for(j=0;j<n-1;j++) { int min=INF,idx=-1; for(i=0;i<n;i++) if(!vis[i]&&d[i]<min) min=d[i],idx=i; vis[idx]=true; if(min==INF) break; for(i=0;i<n;i++) if(!vis[i]&&w[idx][i]) { if(d[idx]+w[idx][i]<d[i]) { num[i]=num[idx]; d[i]=d[idx]+w[idx][i]; path[i]=idx; totalhp[i]=totalhp[idx]+hp[i]; l[i]=l[idx]+1; av_hp[i]=totalhp[i]/l[i]; } else if(d[idx]+w[idx][i]==d[i]) { num[i]+=num[idx]; if(totalhp[idx]+hp[i]>totalhp[i]||(totalhp[idx]+hp[i]==totalhp[i]&&l[idx]+1<l[i])) { path[i]=idx; totalhp[i]=totalhp[idx]+hp[i]; l[i]=l[idx]+1; av_hp[i]=totalhp[i]/l[i]; } } } } } int main() { scanf("%d%d",&n,&m); int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) w[i][j]=INF; char a1[10]; scanf("%s",a1); mp[a1]=0; char a[10]; int t; for(i=1;i<n;i++) { scanf("%s",a),scanf("%d",&t); str[i]=a,mp[a]=i,hp[i]=t; } char b[10]; for(i=0;i<m;i++) { scanf("%s%s%d",a,b,&t); int x=mp[a],y=mp[b]; if(t<w[x][y]) w[x][y]=w[y][x]=t; } i=mp["ROM"]; Dj(0); printf("%d %d %d %d\n",num[i],d[i],totalhp[i],av_hp[i]); vector<int> v; j=path[i]; while(j!=0) v.push_back(j),j=path[j]; i=v.size()-1; printf("%s->",a1); for(j=i;j>=0;j--) printf("%s->",str[v[j]].c_str()); printf("ROM\n"); return 0; } 这个代码为什么是错的。 这一行改成 printf("%d %d %d %d\n",num[i],d[i],totalhp[i],totalhp[i]/l[i]); 就对了。 为什么。两者有区别吗
点赞 回复 分享
发布于 2015-11-19 07:30

相关推荐

面试摇了我吧:啊哈哈面试提前五个小时发,点击不能参加就是放弃
点赞 评论 收藏
分享
10-13 17:47
门头沟学院 Java
wulala.god:图一那个善我面过,老板网上找的题库面的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务