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\n");
120         }
121         else
122             printf("%lld\n",minn);
123     }
124     return 0;
125 }
View Code

 

posted @ 2016-01-29 14:33  sCjTyC  阅读(216)  评论(0编辑  收藏  举报