zoukankan      html  css  js  c++  java
  • hdu2363 枚举最短路

    (1) 二分
        把所有的高度都拿过来,组合起来,sort一遍,然后二分,找到能连通的最小的那个,但这里存在一起情况,就是遇到高度差相等的时候会bug....

    (2) 枚举 连通直接break
        把所有的高度都拿过来,组合起来,soet一遍,然后暴力枚举上下限制,能连通直接break;这个显然是错的,直接break的话只能保证高度差最小,不能保证路径最短..

    (3) 枚举 连通并且高度变化的时候 break;就是在(2)的基础上不直接break,如果第一次找到能连接1,n的路径直接记录当前高度差,然后一直往后跑到高度差不等于第一次连通的高度差的时候break;这样做肯定是对的,但是时间复杂度我感觉过不去....

    (4) 写到第三部我突然想到一个自己感觉正确的方法,因为手懒就不写那个代码了,直接说思路,就是hash + 二分,我们枚举出所有范围组合的后排序,排序后吧所有高度差相同的hash成一个点,每次如果这个点中的某一个点使其连通了,那么这个点就是可行点(如果多个都满足记得保留最优),直接mid = up = mid - 1.......,感觉这样应该会好点..虽然没有去实现,感觉会优化很多时间吧...

    下面是(3)的代码,虽然ac了,但自认为会TLE..



    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<algorithm>
    
    #define N_node 100 + 20
    #define N_edge 10000 + 500
    #define INF 2000000000
    
    using namespace std;
    
    typedef struct
    {
       int to ,next ,cost;
    }STAR;
    
    typedef struct
    {
       int low ,up ,d;
    }HHH;
    
    STAR E[N_edge];
    HHH DH[100*100+100];
    int list[N_node] ,tot;
    int s_x[N_node];
    int H[N_node];
    
    
    void add(int a, int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
    }
    
    bool camp(HHH a ,HHH b)
    {
       return a.d < b.d;
    }
    
    int abss(int x)
    {
       return x > 0 ? x : -x;
    }
    
    void SPFA(int s ,int n ,int low ,int up)
    {
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = INF;
       int mark[N_node] = {0};
       s_x[s] = 0;
       mark[s] = 1;
       queue<int>q;
       q.push(s);
       while(!q.empty())
       {
          int tou ,xin;
          tou = q.front();
          q.pop();
          mark[tou] = 0;
          for(int k = list[tou] ;k ;k = E[k].next)
          {
             xin = E[k].to;
             if(H[xin] < low || H[xin] > up) continue;
             if(s_x[xin] > s_x[tou] + E[k].cost)
             {
                s_x[xin] = s_x[tou] + E[k].cost;
                if(!mark[xin])
                {
                   mark[xin] = 1;
                   q.push(xin);
                }
             }
          }
       }
       return ; 
    }
    
    int main ()
    {
       int t ,i ,j ,n ,m;
       int a ,b ,c;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d %d" ,&n ,&m);
          for(i = 1 ;i <= n ;i ++)
          scanf("%d" ,&H[i]);
          memset(list ,0 ,sizeof(list));
          tot = 1;
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             add(a,b,c);
             add(b,a,c);
          }
          
          int tmp = 0;
          for(i = 1 ;i <= n ;i ++)
          for(j = i + 1 ;j <= n ;j ++)
          {
             int low = H[i] < H[j] ? H[i] : H[j];
             int up  = H[i] > H[j] ? H[i] : H[j];
             DH[++tmp].low = low;
             DH[tmp].up = up;
             DH[tmp].d = up - low;
          }  
          sort(DH + 1 ,DH + tmp + 1,camp);
          
          int minc = INF,minz = 0;
          for(i = 1 ;i <= tmp ;i ++)
          {
             if(H[1] < DH[i].low || H[1] > DH[i].up) continue;
             if(H[n] < DH[i].low || H[n] > DH[i].up) continue;
             SPFA(1 ,n ,DH[i].low ,DH[i].up);
             if(s_x[n] == INF) continue;
             
             if(minc == INF)
             {
                minc = DH[i].d;
                minz = s_x[n];
             }
             else
             {
                if(minc != DH[i].d) break;
                if(s_x[n] < minz)
                minz = s_x[n];
             }     
          } 
          if(n == 1) printf("0 0
    ");
          else printf("%d %d
    " ,minc ,minz);
       }
       return 0;
    }
          
    

  • 相关阅读:
    make menuconfig出现乱码
    内存中的变量和值
    is&==
    python小整数池
    生成器
    GIL
    grub rescue问题修复
    期末考试
    期末要求
    选课练习
  • 原文地址:https://www.cnblogs.com/csnd/p/12063202.html
Copyright © 2011-2022 走看看