zoukankan      html  css  js  c++  java
  • PAT甲级练习 1087 All Roads Lead to Rome (30分) 字符串hash + dijkstra

    题目分析:

    这题我在写的时候在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 } 
  • 相关阅读:
    用例的粒度问题
    REST和RPC最大区别
    成功的结对编程要点
    我认为技术经理应该做的事儿
    敏捷测试实践
    DDD-围绕业务逻辑编程
    依赖反转原则
    Kafka和Rabbitmq的最大区别
    Cassandra快速两次写入导致顺序不对的问题
    DotNetBar之SupergridControl显示图片,行距自动调整
  • 原文地址:https://www.cnblogs.com/YLTFY1998/p/12266262.html
Copyright © 2011-2022 走看看