OpenJudge P4124海贼王之伟大航路

解题思路:

利用深度优先搜索找到经历1到n-1的路径然后再从n-1到n,结合最优性剪枝。

如果当前已经找到的最优路径时间为T,那么以后总时间已经大于T的走法就可以直接放弃。

如果之前到达某个状态比这次花费的时间要少,则剪枝。

如何表示某个状态呢,该状态可以去掉1和n,只与当前所在城市和走过的城市有关,那么可以设城市2为2^0,城市3为2^1……

就可以用zta[14][1<<14]表示到达该点且同时经过某些点时所用的最少时间。

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 const int inf = 0x3f3f3f3f;
 5 int n;
 6 int timeList[20][20];
 7 int ans;
 8 int totaltime;
 9 bool visited[20];
10 int zta[14][1<<14];
11 int zt;
12 int pow2[20];
13 int all;
14 void dfs(int s)
15 {
16     if(zt==all)
17     {
18         int t=totaltime+timeList[s][n];
19         if(t<ans)
20             ans=t;
21         return;
22     }
23     for(int i=2; i<n; i++)
24     {
25         if(visited[i] == 1)
26             continue;
27         if(totaltime+timeList[s][i] >= ans)
28             continue;
29         if(zta[i-2][zt+pow2[i-2]] <= totaltime+timeList[s][i])
30             continue;
31         visited[i]=1;
32         totaltime+=timeList[s][i];
33         zt+=pow2[i-2];
34         zta[i-2][zt]=totaltime;
35         dfs(i);
36         visited[i]=0;
37         totaltime-=timeList[s][i];
38         zt-=pow2[i-2];
39     }
40 }
41 void init()
42 {
43     ans=inf;
44     memset(visited,0,sizeof(visited));
45     visited[1]=1;
46     memset(zta,inf,sizeof(zta));
47     zt=0;
48     for(int i=0; i<14; i++)
49         pow2[i]=(1<<i);
50     all=0;
51     for(int i=0; i<n-2; i++)
52         all+=pow2[i];
53     totaltime=0;
54     return ;
55 }
56 int main()
57 {
58     cin>>n;
59     for(int i=1; i<=n; i++)
60         for(int j=1; j<=n; j++)
61             cin>>timeList[i][j];
62     init();
63     dfs(1);
64     cout<<ans<<endl;
65 }

 

posted @ 2017-04-20 15:45  Kearon  阅读(1001)  评论(0编辑  收藏  举报