zoukankan      html  css  js  c++  java
  • Travelling(hdu3001)

    Travelling

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5762    Accepted Submission(s): 1857


    Problem Description
    After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.
     
    Input
    There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.
     
    Output
    Output the minimum fee that he should pay,or -1 if he can't find such a route.
     
    Sample Input
    2 1
    1 2 100
    3 2
    1 2 40
    2 3 50
    3 3
    1 2 3
    1 3 4
    2 3 10

    Sample Output

    100
    90
    7
    题意:有N个城市,一个人要 经过每个点,且经过每个点不超过2次。求最少的路费。可以从任意一个点开始。
    思路:TSP,这个是三进制的状态压缩,因为过每个点要求不超过两次,其余dp的思路和TSP二进制差不多,可以说一样。
    dp[i][j]表示在状态i下以j点结束的所要的最小费用。 dp[i][j]=min(dp[i][j],dp[cc][v]+ma[v][j]);cc,表示i的上一个状态。
    代码:
      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<string.h>
      4 #include<iostream>
      5 #include<stdlib.h>
      6 #include<queue>
      7 #include<stack>
      8 typedef long long ll;
      9 long long  ma[20][20];
     10 long long dp[60000][20];//开pow(3,11);
     11 long long san[60000][20];
     12 int a[60000];//记录状态是否都至少经过一次
     13 const long long N=1e9;
     14 using  namespace std;
     15 int main(void)
     16 {
     17     long long  n,i,j,k,p,q;
     18     long long  x,y,v;
     19     memset(san,0,sizeof(san));
     20     for(i=0; i<60000; i++)
     21     {
     22         ll vv=i;
     23         int flag=0;
     24         int f=0;
     25         while(vv)
     26         {
     27             san[i][f++]=vv%3;
     28             if(vv%3==0)
     29             {
     30                 flag=1;
     31             }
     32             vv/=3;
     33 
     34         }
     35         if(flag==0) a[i]=1;
     36     }//把状态用三进制表示
     37     while(scanf("%lld %lld",&p,&q)!=EOF)
     38     {
     39         for(i=0; i<20; i++)
     40             for(j=0; j<20; j++)
     41                 ma[i][j]=N;
     42         for(i=0; i<60000; i++)
     43             for(j=0; j<20; j++)
     44                 dp[i][j]=N;
     45         for(i=0; i<q; i++)
     46         {
     47             scanf("%lld %lld %lld",&x,&y,&k);
     48             ma[x-1][y-1]=min(k,ma[x-1][y-1]);
     49             ma[y-1][x-1]=min(k,ma[x-1][y-1]);
     50         }
     51         int xx=1;
     52         for(i=0; i<p; i++)
     53         {
     54             dp[xx][i]=0;
     55             xx*=3;
     56         }//出发点初始化置0。
     57         int yy=1;
     58         for(i=0; i<p; i++)
     59         {
     60             yy*=3;
     61         }
     62         for(i=1; i<yy; i++)
     63         {
     64             ll pp=i;
     65             for(j=0; j<p; j++)
     66             {
     67                 if(san[pp][j]>0)//判断当前状态是否经过这点
     68                 {
     69                     int uu=0;
     70                     int rr=1;
     71                     for(v=0; v<p; v++)
     72                     {
     73                         int vp=san[pp][v];
     74                         if(v==j)
     75                         {
     76                             vp--;
     77                         }
     78                         vp*=rr;
     79                         rr*=3;
     80                         uu+=vp;
     81                     }
     82                     for(v=0; v<p; v++)
     83                     {
     84                         if(san[uu][v]>0)//判断上个状态是否经过上个状态的结束点
     85                         {
     86                             dp[i][j]=min(dp[i][j],dp[uu][v]+ma[v][j]);
     87 
     88                         }
     89                     }
     90                 }
     91             }
     92 
     93         }
     94         long long minn=N;
     95         int tu=0;
     96         for(i=0; i<p; i++)
     97         {
     98             tu*=3;
     99             tu+=1;
    100         }
    101         for(i=tu; i<yy; i++)//至少经过每个点一次中取最小
    102         {
    103             if(a[i])
    104             {
    105                 for(j=0; j<p; j++)
    106                 {
    107                     if(dp[i][j]<minn)
    108                     {
    109                         minn=dp[i][j];
    110                     }
    111 
    112                 }
    113             }
    114 
    115         }
    116 
    117         if(minn==N)
    118         {
    119             printf("-1
    ");
    120         }
    121         else
    122             printf("%lld
    ",minn);
    123     }
    124     return 0;
    125 }
    View Code
    油!油!you@
  • 相关阅读:
    暑假第二十七测
    暑假第二十七测
    【真题解】牛宫
    【伪题解】牛宫
    最优贸易
    跳马问题
    求和问题
    【题解】山区建小学
    OpenStack之虚机冷迁移代码简析
    OpenStack之虚机热迁移代码解析
  • 原文地址:https://www.cnblogs.com/zzuli2sjy/p/5168927.html
Copyright © 2011-2022 走看看