1087. All Roads Lead to Rome (30)
2015-09-08 22:22
363 查看
题目链接:http://www.patest.cn/contests/pat-a-practise/1087
题目:
Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<=N<=200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines
each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format "City1 City2 Cost". Here the name of a city is a
string of 3 capital English letters, and the destination is always ROM which represents Rome.
Output Specification:
For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommended. If such a route is still not unique, then we output the one with the maximum average happiness
-- it is guaranteed by the judge that such a solution exists and is unique.
Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommended route. Then in the next line, you are supposed
to print the route in the format "City1->City2->...->ROM".
Sample Input:
Sample Output:
分析:
复杂的Dijkstra扩展,找到cost最短的,cost相同就找happy最大的,happy相同找平均happy最大的,而且还要记录路径,采用的方法是对每个节点维护一个vector,里面放一个记录信息record*,构成vector<record*>vec,record中需要记录当前经过的城市数(方便计算average),以及父节点,平均happy数,以及Happy_sum。
因为我想做到的目标不仅是题目要求的那么简单,我还想要把所有cost的相同的路径保存下来(否则的话我只要保留一条cost和happy都最大的就行,有且只有一条)
出错是因为不能用average来判断,因为有如下图情况,可以看到,从左边和右边cost都是相同的,但是左边的happy比右边的大,可是从average来说,反而是右边的average大,所以要把happy_max放入每个节点中,并且还要把Happy_max的判断加入,因为会有如下情况,左边和右边的averag是一样的,Int的除法的问题。
AC代码:
截图:
P.S:
另外附上小双的代码,更简单明了:
——Apie陈小旭
题目:
Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<=N<=200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N-1 lines
each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format "City1 City2 Cost". Here the name of a city is a
string of 3 capital English letters, and the destination is always ROM which represents Rome.
Output Specification:
For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommended. If such a route is still not unique, then we output the one with the maximum average happiness
-- it is guaranteed by the judge that such a solution exists and is unique.
Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommended route. Then in the next line, you are supposed
to print the route in the format "City1->City2->...->ROM".
Sample Input:
6 7 HZH ROM 100 PKN 40 GDN 55 PRS 95 BLN 80 ROM GDN 1 BLN ROM 1 HZH PKN 1 PRS ROM 2 BLN HZH 2 PKN GDN 1 HZH PRS 1
Sample Output:
3 3 195 97 HZH->PRS->ROM
分析:
复杂的Dijkstra扩展,找到cost最短的,cost相同就找happy最大的,happy相同找平均happy最大的,而且还要记录路径,采用的方法是对每个节点维护一个vector,里面放一个记录信息record*,构成vector<record*>vec,record中需要记录当前经过的城市数(方便计算average),以及父节点,平均happy数,以及Happy_sum。
因为我想做到的目标不仅是题目要求的那么简单,我还想要把所有cost的相同的路径保存下来(否则的话我只要保留一条cost和happy都最大的就行,有且只有一条)
出错是因为不能用average来判断,因为有如下图情况,可以看到,从左边和右边cost都是相同的,但是左边的happy比右边的大,可是从average来说,反而是右边的average大,所以要把happy_max放入每个节点中,并且还要把Happy_max的判断加入,因为会有如下情况,左边和右边的averag是一样的,Int的除法的问题。
AC代码:
#include<cstdio> #include<iostream> #include<string> #include<vector> #include<map> using namespace std; int happy[202]; int cost[202][202]; struct record{ int citys;//表示从起点开始经过的城市数目 int parent;//表示上一个节点 int average;//表示平均的开心数 int happy_all;//表示此条路径的开心总数 record() :citys(0), parent(-1), average(-1) {} }; bool mark[202]; int dist[202]; int happy_sum[202]; vector<record*>vec[202]; map<string, int>S2I;//字符串转化为数字 map<int, string>I2S;//数字转化为字符串 void dij(int s, int t,int city_num){ mark[s] = true; dist[s] = 0; happy_sum[s] = happy[s]; int newP = s; record *rec_s = new record(); rec_s->citys = 1; rec_s->parent = -1; rec_s->happy_all = happy[s]; rec_s->average = rec_s->happy_all / rec_s->citys; vec[s].push_back(rec_s); while (!mark[t]){ for (int i = 0; i < city_num; ++i){ if (cost[newP][i] == -1 || cost[newP][i] == 0 || mark[i])continue; else if (dist[i] == -1 || dist[i] > dist[newP] + cost[newP][i]){ //如果有更小距离的,那么把vec清空,并且根据newP节点的所有路径构建record dist[i] = dist[newP] + cost[newP][i]; vec[i].clear(); //happy_sum[i] = happy_sum[newP] + happy[i]; for (int j = 0; j < vec[newP].size(); j++){ record *rec = new record(); rec->citys = vec[newP][j]->citys + 1; rec->parent = newP; rec->happy_all = vec[newP][j]->happy_all + happy[i]; //rec->average = happy_sum[i] / (rec->citys - 1); rec->average = rec->happy_all / (rec->citys - 1); vec[i].push_back(rec); } } else if (dist[i] == dist[newP] + cost[newP][i]){ //如果最短距离相同,则构造record添加到vec中 for (int j = 0; j < vec[newP].size(); j++){ record *rec = new record(); rec->citys = vec[newP][j]->citys + 1; rec->parent = newP; rec->happy_all = vec[newP][j]->happy_all + happy[i]; rec->average = rec->happy_all / (rec->citys - 1); vec[i].push_back(rec); } } } int min = 0x7fffffff; for (int i = 0; i < city_num; ++i){ if (mark[i] || dist[i] == -1)continue; if (dist[i] < min){ min = dist[i]; newP = i; } } mark[newP] = true; }//while } void printPath(int start_city, int end_city, int max_idx){ //打印路径 if (end_city != start_city){ int parent = vec[end_city][max_idx]->parent; int parent_max = 0; int max = 0; int happy_max = 0; for (int i = 0; i < vec[parent].size(); ++i){ if (vec[parent][i]->happy_all > happy_max || (vec[parent][i]->happy_all == happy_max && vec[parent][i]->average > max)){ parent_max = i; max = vec[parent][i]->average; happy_max = vec[parent][i]->happy_all; } } printPath(start_city, parent, parent_max); cout << I2S[parent] << "->"; } } int main(){ freopen("F://Temp/input.txt", "r", stdin); int city_num, road_num; for (int i = 0; i < 202; i++){ happy[i] = 0; dist[i] = -1; mark[i] = false; happy_sum[i] = 0; vec[i].clear(); for (int j = 0; j < 202; ++j) cost[i][j] = -1; cost[i][i] = 0; } S2I.clear(); I2S.clear(); string start_city_str; int start_city; cin >> city_num >> road_num >> start_city_str; int idx = 0; if (S2I.find(start_city_str) == S2I.end()){ S2I[start_city_str] = idx; I2S[idx] = start_city_str; start_city = idx; idx++; } for (int i = 0; i < city_num - 1; ++i){ string str_input; int happy_input; cin >> str_input >> happy_input; if (S2I.find(str_input) == S2I.end()){ S2I[str_input] = idx; I2S[idx] = str_input; happy[idx] = happy_input; idx++; } } for (int i = 0; i < road_num; ++i){ string str_start, str_end; int cost_input; cin >> str_start >> str_end >> cost_input; cost[S2I[str_start]][S2I[str_end]] = cost[S2I[str_end]][S2I[str_start]] = cost_input; } int end_city = S2I["ROM"]; dij(start_city,end_city,city_num); int max_idx = 0; int max = 0; int happy_max = 0; for (int i = 0; i < vec[end_city].size(); ++i){ if (vec[end_city][i]->happy_all > happy_max || (vec[end_city][i]->happy_all == happy_max && vec[end_city][i]->average > max)){ //这里的判断条件一定要写对,详见附图,因为有happy总数不一样,而平均happy数一样的情况 //我第一次写的是vec[end_city][i]->happy_all > happy_max && vec[end_city][i]->average > max出错了 max_idx = i; max = vec[end_city][i]->average; happy_max = vec[end_city][i]->happy_all; } } cout << vec[end_city].size() << " " << dist[end_city] << " " << happy_max << " " << max << endl; printPath(start_city, end_city, max_idx); cout << "ROM" << endl; return 0; }
截图:
P.S:
另外附上小双的代码,更简单明了:
#include <iostream> #include <cstdio> #include <map> #include <string> #include <vector> #include <climits> using namespace std; //每个城市结点 struct Edge { int cost; int next; }; struct Node { int value; string str; vector<Edge> next; int distant, happy; // 第i个结点距离起始城市的最小距离和最大happy int rNums; // 到第i个结点的最短路径的条数 int pNums; // 到第i个结点最大幸福经历的最少结数 bool visit; int parent; //最大幸福的前一个结点, Node():distant(INT_MAX), happy(0), rNums(INT_MAX), pNums(0), visit(false), parent(-1) { next.clear(); } }; const int N = 201; map<string, int> mp; //城市名字到结点编号的映射 Node node ; // int seq ; int main(void) { int n, k; scanf("%d%d", &n, &k); string startS; cin >> startS; mp[startS] = 0; node[0].value = 0; node[0].distant = 0; node[0].rNums = 0; node[0].pNums = 1; node[0].str = startS; string city; int value; for (int i = 1; i < n; ++i) { cin >> city >> value; mp[city] = i; node[i].value = value; node[i].str = city; } string city1, city2; int c1, c2; Edge edge; for (int i = 0; i < k; ++i) { cin >> city1 >> city2 >> edge.cost; c1 = mp[city1]; c2 = mp[city2]; edge.next = c2; node[c1].next.push_back(edge); edge.next = c1; node[c2].next.push_back(edge); } city = "ROM"; int romIndex = mp[city]; while (true) { int minIndex = -1, minDistant = INT_MAX; for (int i = 0; i < n; ++i) { if (node[i].visit == false && node[i].distant < minDistant) { minIndex = i; minDistant = node[i].distant; } } if (minIndex == -1) break; node[minIndex].visit = true; if (minIndex == romIndex) break; for (vector<Edge>::iterator iter = node[minIndex].next.begin(); iter != node[minIndex].next.end(); ++iter) { if (node[iter->next].visit == true) continue; else { if (node[minIndex].distant + iter -> cost < node[iter -> next].distant) { node[iter -> next].distant = node[minIndex].distant + iter -> cost; node[iter -> next].parent = minIndex; node[iter -> next].happy = node[minIndex].happy + node[iter -> next].value; node[iter -> next].pNums = node[minIndex].pNums; node[iter -> next].rNums = node[minIndex].rNums + 1; } else if (node[minIndex].distant + iter -> cost == node[iter -> next].distant) { node[iter -> next].pNums += node[minIndex].pNums; if ((node[iter -> next].happy < node[minIndex].happy + node[iter -> next].value)) { node[iter -> next].happy = node[minIndex].happy + node[iter -> next].value; node[iter -> next].rNums = node[minIndex].rNums + 1; node[iter -> next].parent = minIndex; } } } } } printf("%d %d %d %d\n", node[romIndex].pNums, node[romIndex].distant, node[romIndex].happy, node[romIndex].happy / node[romIndex].rNums); int index = 0; while (romIndex != -1) { seq[index++] = romIndex; romIndex = node[romIndex].parent; } --index; cout << node[seq[index]].str; for (int i = index - 1; i >= 0; --i) { printf("->"); cout << node[seq[i]].str; } printf("\n"); return 0; }
——Apie陈小旭
相关文章推荐
- Websocket实例
- 杭州面试总结
- Jdk5.0泛型
- 模拟ATM机(缺少文件操作部分,不能实现真正意义上的存储)
- android 实现应用卸载反馈
- POJ 3237(树链剖分)
- hdu 4279 Number(找规律)
- Vim配置
- PWM实现ADC和DAC
- JQuery的工具方法
- Android控件之Spinner用法实例分析
- 状态管理
- 用Nagios监控OSSIM中MySQL数据库
- 秋意浓
- 二十三种设计模式之创建型模式之单态模式
- 好用的视频编码转换工具
- Windows10 + Matlab2013 mex C++ 调用gsl
- ICMP
- bzoj2019 [Usaco2009 Nov]找工作
- 中小企业 IT 运维福利:快速构建 on-call 机制