HDU3001 Travelling

题目:

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.

输入:

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 the minimum fee that he should pay,or -1 if he can't find such a route.

样例:

分析:用欧拉路(DFS)交了几发都TLE了,非常咸鱼的开始搜题解:状压dp?为什么在进阶搜索专题。。。

还有一个坑,题目数据最大n=10,状态最多3的十次方,是小于56000的但用56000就TLE。。。换大一点就ac了

 1 #include<iostream>
 2 #include<sstream>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<string>
 6 #include<cstring>
 7 #include<algorithm>
 8 #include<functional>
 9 #include<iomanip>
10 #include<numeric>
11 #include<cmath>
12 #include<queue>
13 #include<vector>
14 #include<set>
15 #include<cctype>
16 const double PI = acos(-1.0);
17 const int INF = 0x3f3f3f3f;
18 const int NINF = -INF - 1;
19 typedef long long ll;
20 #define MOD 1000007
21 using namespace std;
22 int n, m;
23 int three[11];//记录共有多少种状态(题目数据最多10,每个城市3种情况,共3的10次方)
24 int cur[60000][11];//每种状态下每个城市情况
25 int G[11][11], dp[60000][11];//G表示图,dp的i表示状态,j表示到第j位该状态路线截至
26 void ini()
27 {
28     three[0] = 1;
29     for (int i = 1; i <= 10; ++i) three[i] = three[i - 1] * 3;
30     for (int i = 1; i <= three[10]; ++i)
31     {
32         int tmp = i;
33         for (int j = 1; j <= 10; ++j)//十进制的状态转换对应三进制,每位表明对应城市情况
34         {
35             cur[i][j] = tmp % 3;
36             tmp /= 3;
37         }
38     }
39 }
40 int main()
41 {
42     ini();//预处理,状态压缩
43     while (scanf("%d %d", &n, &m) != EOF)
44     {
45         for (int i = 1; i <= n; ++i)
46         {
47             for (int j = 1; j <= n; ++j)
48                 G[i][j] = INF;
49         }
50         for (int i = 1; i <= three[n]; ++i)
51         {
52             for (int j = 1; j <= n; ++j)
53                 dp[i][j] = INF;
54         }
55         for (int i = 1; i <= m; ++i)
56         {
57             int u, v, cost;
58             cin >> u >> v >> cost;
59             G[u][v] = G[v][u] = min(cost, G[u][v]);//可能有重边
60         }
61         for (int i = 1; i <= n; ++i) dp[three[i - 1]][i] = 0;//起始状态从不同点出发
62         int ans = INF;
63         for (int i = 1; i <= three[n]; ++i)//i状态
64         {
65             bool flag = 0;
66             for (int j = 1; j <= n; ++j)//j为原路的最后一个点
67             {
68                 if (cur[i][j] == 0) flag = 1;//如果该状态不存在某个位等于0说明该状态达成目标
69                 if (dp[i][j] != INF)
70                 {
71                     for (int k = 1; k <= n; ++k)//k为从j起始的新增点
72                     {
73                         if (G[j][k] != INF && cur[i][k] != 2)//对于走过两次的点不能再走
74                             dp[i + three[k - 1]][k] = min(dp[i][j] + G[j][k], dp[i + three[k - 1]][k]);//状态转移方程
75                     }
76                 }
77             }
78             if (!flag)//对于达成目标的状态取他们的费用最小
79             {
80                 for (int j = 1; j <= n; ++j)
81                     ans = min(ans, dp[i][j]);
82             }
83         }
84         if (ans == INF) cout << -1 << endl;
85         else cout << ans << endl;
86     }
87     return 0;
88 }
原文地址:https://www.cnblogs.com/veasky/p/11120876.html