【DP】 HDU 3001 Travelling 3进制状压
变形题
0表示没走过
1表示走过一次
2表示走过两次
#include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <iostream> #include <algorithm> #include <sstream> #include <cmath> using namespace std; #include <queue> #include <stack> #include <vector> #include <deque> #include <map> #define cler(arr, val) memset(arr, val, sizeof(arr)) typedef long long LL; const int MAXN = 200000+6; const int MAXM = 240000; const int INF = 0x3f3f3f3f; const int mod = 1000000007; int n,m; int dp[MAXN][10]; int mp[14][14],num[13],a[13]; int ArrayToInt(int a[]) { int ret=0; for(int i=n-1;i>=0;i--) { ret*=3; ret+=a[i]; } return ret; } void intToArray(int x) { for(int i=0;i<n;i++) { a[i]=x%3; x/=3; } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif int x,y,c; num[0]=1; for(int i=1;i<=11;i++) num[i]=num[i-1]*3; for(int i=0;i<=10;i++) printf("%d ",num[i]); puts(""); while(cin>>n>>m) { cler(dp,INF); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) mp[i][j]=INF; for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&c); y--,x--; mp[y][x]=mp[x][y]=min(mp[x][y],c); } for(int i=0;i<n;i++) dp[num[i]][i]=0; int ans=INF; for(int i=0;i<num[n];i++) { for(int u=0;u<n;u++)//现在位置 { intToArray(i);//得到每位状态 if(a[u]==0) continue; if(dp[i][u]==INF) continue; bool flag=true; for(int t=0;t<n;t++) if(a[t]==0)//每位都要走过 0表示没走 flag=false; if(flag)ans=min(ans,dp[i][u]); for(int v=0;v<n;v++) { if(u==v||mp[u][v]==INF||a[v]>=2) continue; a[v]++; int s=ArrayToInt(a); dp[s][v]=min(dp[s][v],dp[i][u]+mp[u][v]); a[v]--; } } } if(ans==INF) cout<<-1<<endl; else cout<<ans<<endl; } return 0; }