状压dp-----三进制
三进制的状压dp要先预处理3^n以及每一个数的每一位
例题
hdu3001
题意:
给定n 个城市已经 m 条路 以及对应路费 c,要求遍历所有城市最少的路费,每个城市不能超过2次。
题解:
看代码吧。。
代码:
#include <bits/stdc++.h> using namespace std; int n,m,minn; int load[12][12]; int bit[12]; int dp[60000][12]; int num[60000][12]; #define INF 1e8 int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); std::ios::sync_with_stdio(false); bit[0]=1; for (int i=1;i<=11;i++) bit[i]=bit[i-1]*3; for (int i=0;i<bit[10];i++) { int b=i; for (int j=0;j<10;j++) { num[i][j]=b%3; b/=3; } } while (cin>>n>>m) { memset(load,-1,sizeof(load)); for (int i=0;i<m;i++) { int a,b,c; cin>>a>>b>>c; a--;b--; if (load[a][b]==-1) load[a][b]=load[b][a]=c; else load[a][b]=load[b][a]=min(load[a][b],c); } memset(dp,-1,sizeof(dp)); int flag,next; for(int j = 0; j < n; j++) dp[ bit[j] ][j] = 0; minn=INF; for(int i=0;i<bit[n];i++) { flag=1; for (int j=0;j<n;j++) { if (num[i][j]==0) flag=0; if (dp[i][j]==-1) continue; for (int k=0;k<n;k++) { if (j==k||num[i][k]==2||load[k][j]==-1) continue; next=i+bit[k]; if (dp[next][k]==-1) dp[next][k]=dp[i][j]+load[j][k]; else dp[next][k]=min(dp[next][k],dp[i][j]+load[j][k]); } } if (flag==1) { for (int j=0;j<n;j++) if (dp[i][j]!=-1) minn=min(minn,dp[i][j]); } } if(minn == INF) minn = -1; printf("%d\n", minn); } return 0; }