题目分析:
这题我在写的时候在PTA提交能过但是在牛客网就WA了一个点,先写一下思路留个坑
这题的简单来说就是需要找一条最短路->最开心->点最少(平均幸福指数自然就高了),由于本题给出的所有的城市的名称都是字符串(三个大写字母),所以我先将每个字符串计算一个hash值去代表每一个城市,接着就是用dijkstra算法去逐步判断各种情况,是直接用了一个dijkstra去计算,而没有说是先dijkstra算出最短距离再dfs所有的路径去找出最优解,因为我觉得这题局部最优就能反映到全局最优,也不知是不是想错了才在牛客上有一个点过不去QAQ...
本题代码:
1 #include<iostream> 2 #include<vector> 3 #include<stdio.h> 4 #include<string.h> 5 #include<cmath> 6 #include<string> 7 #include<algorithm> 8 #include<map> 9 using namespace std; 10 11 const int N = 3000; 12 const int M = 0x3f3f3f3f; 13 int mat[N][N]; 14 int dist[N]; 15 int vis[N]; 16 int hap[N]; 17 int get_hap[N]; //已知情况下到i点能获得的幸福值 18 int way[N]; //到达每个点有多少种走法 19 int num[N]; //到达i点需要走多少个点 第一个sta不算 20 vector<int> v[N]; 21 int pre[N]; 22 map<int, string> mp; 23 int n, m, min_dist, max_hap; 24 25 int trans(string s){ 26 int len = s.size(); 27 int sum = 0; 28 for(int i = 0; i < len; i++){ 29 sum = sum * 10 + s[i] - 'A'; 30 } 31 return sum; 32 } 33 34 int minn(){ 35 int Min = M; 36 int k = -1; 37 for(int i = 0; i < 3000; i++){ 38 if(vis[i] == 0 && dist[i] < Min){ 39 Min = dist[i]; 40 k = i; 41 } 42 } 43 return k; 44 } 45 46 void out(int x){ 47 if(pre[x] == -1){ 48 cout<<mp[x]; 49 return; 50 }else{ 51 out(pre[x]); 52 cout<<"->"<<mp[x]; 53 return; 54 } 55 } 56 57 void dijkstra(int st){ 58 memset(dist, M, sizeof(dist)); 59 for(int i = 0; i < v[st].size(); i++) dist[v[st][i]] = mat[st][v[st][i]]; 60 dist[st] = 0; //保证自己先选自己 61 way[st] = 1; //到自己有一条路 62 pre[st] = -1; 63 for(int i = 1; i <= n; i++){ 64 int k = minn(); 65 if(k == -1) break; 66 vis[k] = 1; 67 for(int j = 0; j < 3000; j++){ 68 if(vis[j] == 0 && dist[k] + mat[k][j] < dist[j]){ 69 dist[j] = dist[k] + mat[k][j]; 70 get_hap[j] = hap[j] + get_hap[k]; 71 pre[j] = k; 72 way[j] = way[k]; 73 num[j] = num[k] + 1; 74 }else if(vis[j] == 0 && dist[k] + mat[k][j] == dist[j]){ 75 way[j] = way[j] + way[k]; 76 if(get_hap[k] + hap[j] > get_hap[j]){ //距离相同但是更快乐 77 get_hap[j] = get_hap[k] + hap[j]; 78 pre[j] = k; 79 num[j] = num[k] + 1; 80 }else if(get_hap[k] + hap[j] == get_hap[j]){//距离相同且同样快乐则比较点的个数 81 if(num[k] + 1 < num[j]){ //点更少 82 pre[j] = k; 83 num[j] = num[k] + 1; 84 } 85 } 86 } 87 } 88 } 89 int en = trans("ROM"); 90 printf("%d %d %d %d ", way[en], dist[en], get_hap[en], get_hap[en]/num[en]); 91 out(en); 92 printf(" "); 93 } 94 95 int main(){ 96 scanf("%d%d", &n, &m); 97 string sta; 98 cin>>sta; 99 int st = trans(sta); 100 mp[st] = sta; 101 memset(vis, 0, sizeof(vis)); 102 memset(hap, 0, sizeof(hap)); 103 memset(mat, M, sizeof(mat)); 104 memset(num, 0, sizeof(num)); 105 memset(get_hap, 0, sizeof(get_hap)); 106 memset(way, 0, sizeof(way)); 107 for(int i = 1; i < n; i++){ 108 string s; 109 cin>>s; 110 int tt = trans(s); 111 mp[tt] = s; 112 int x; 113 scanf("%d", &x); 114 hap[tt] = x; //根据hash值锁定幸福值 115 } 116 for(int i = 1; i <= m; i++){ 117 string s1, s2; int x; 118 cin>>s1>>s2; scanf("%d", &x); 119 int t1 = trans(s1); 120 int t2 = trans(s2); 121 v[t1].push_back(t2); 122 v[t2].push_back(t1); 123 mat[t1][t2] = x; 124 mat[t2][t1] = x; 125 } 126 dijkstra(st); 127 return 0; 128 }