http://acm.hdu.edu.cn/showproblem.php?pid=3001
题意:小明想去n个城市游玩,m条路,从一个城市到达另一个城市有一定的花费,每个城市最多可以走两次
求最少的花费
题解:因为每个城市最多走两次,可以用三进制,保存状态,感觉同二进制没区别,不过想了半天没想通,
看了一下题解,懂了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define M 60000
#define INF 0x3f3f3f3f
int s[12];
int t[M][12],map[12][12];
int n,m;
int dp[M][12];
void init(){
s[0] = 1;
for(int i = 1;i <= 11;i++){
s[i] = s[i-1] * 3 ;
}
for(int i = 0;i < 59049;i++){
int tmp = i;
for(int j = 0;j < 10;j++){
t[i][j] = tmp % 3;
tmp /= 3;
}
}
}
int main(){
init();
int u,v,w;
while(cin >> n >> m){
memset(map,INF,sizeof(map));
for(int i = 0;i < m;i++){
cin >> u >> v >> w ;
u -- ; v --;
map[u][v] = map[v][u] = min(map[u][v],w);
}
memset(dp,INF,sizeof(dp));
for(int i = 0;i < n;i++)
dp[s[i]][i] = 0; //初始化第i个状态只有1个城市花费为0
int ans = INF;
for(int i = 0;i < s[n];i++){
bool flag = true ;//如果城市都被走过
for(int j = 0;j < n;j++){
if(!t[i][j]) flag = false;
if(dp[i][j] != INF){
for(int k = 0;k < n;k++){
if(k == j || t[i][k] == 2 || map[j][k] == INF) continue;
dp[i+s[k]][k] = min(dp[i+s[k]][k],dp[i][j] + map[j][k]);
}
}
}
if(flag) {
for(int l = 0;l < n;l++){
ans = min(ans,dp[i][l]);
}
}
}
if(ans == INF) cout << "-1" << endl;
else cout << ans << endl;
}
}