HDU-3001 Travelling (State compression)
A person wants to visit all the cities, but the same city does not want to visit more than two times. Now the traffic between cities is provided. He can choose any point as the starting point. What is the lowest fare for visiting all cities?
Solution: This is similar to POJ-3311 Hie with the Pie
The status mark here is represented by a three-digit number, which indicates the number of times each city has been visited.
Set dp [I] [state] to the lowest traffic fee for the current city in I and the city that has been visited to the state.
State transition equation:
Dp [I] [S + I city Mark] = min (dp [I] [S + I city Mark], dp [j] [S] + cost [j] [I])
Pay attention to side Determination
The queue is used again...
#include
#include
#include#include
using namespace std;#define maxn 15#define INF 0x3f3f3f3f#define maxs 60000struct DP { int num, state;}start[maxn];int n, m;int cost[maxn][maxn];int dp[maxn][maxs];int mod[maxn];void init() { int x, y, z; memset(cost, 0x3f, sizeof(cost)); for(int i = 0; i < m; i++) { scanf(%d%d%d, &x, &y, &z); cost[x-1][y-1] = cost[y-1][x-1] = min(cost[x-1][y-1], z); } memset(dp, 0x3f, sizeof(dp)); for(int i = 0; i < n; i++) { dp[i][mod[i]] = 0; start[i].num = i; start[i].state = mod[i]; }}void solve() { queue
q; for(int i = 0; i < n; i++) q.push(start[i]); int ans = INF; while(!q.empty()) { DP t = q.front(); q.pop(); for(int i = 0; i < n; i++) { if(i == t.num || cost[i][t.num] == INF) continue; if(!i && t.state % 3 == 2) continue; if(i && ( (t.state % mod[i+1]) - (t.state % mod[i]) ) / mod[i] == 2) continue; if(dp[i][t.state + mod[i]] > dp[t.num][t.state] + cost[t.num][i]) { dp[i][t.state + mod[i]] = dp[t.num][t.state] + cost[t.num][i]; DP tt; tt.num = i; tt.state = t.state + mod[i]; q.push(tt); bool flag = false; int tmp = t.state + mod[i]; if(dp[i][tmp] < ans) { for(int j = 0; j < n; j++) if(tmp % 3 == 0) { flag = true; break; } else { tmp /= 3; } if(!flag) ans = dp[i][t.state + mod[i]]; } } } } if(ans == INF) ans = -1; printf(%d, ans);}void begin() { mod[0] = 1; for(int i = 1; i < 12; i++) mod[i] = mod[i - 1] * 3;}int main() { begin(); while(scanf(%d%d, &n, &m) != EOF) { init(); solve(); } return 0;}