hdu 3001(状压dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001
思路:这道题类似于TSP问题,只不过题目中说明每个城市至少要走一次,至多走2次,因此要用到三进制压缩,然后就是状态转移方程了:dp[i+State[k]]=min(dp[i+State[k]],dp[i][j]+map[j][k]);
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 int State[12]; 8 int visited[60000][12]; 9 int dp[60000][12]; 10 int map[12][12]; 11 int n,m; 12 13 void Initiate() 14 { 15 State[0]=1; 16 for(int i=1;i<=10;i++) 17 State[i]=State[i-1]*3; 18 for(int i=0;i<=State[10];i++){ 19 int tmp=i; 20 for(int j=0;j<=10;j++){ 21 visited[i][j]=tmp%3; 22 tmp/=3; 23 } 24 } 25 } 26 27 int main() 28 { 29 Initiate(); 30 int u,v,w,ans; 31 while(~scanf("%d%d",&n,&m)){ 32 memset(dp,inf,sizeof(dp)); 33 memset(map,inf,sizeof(map)); 34 for(int i=0;i<n;i++)dp[State[i]][i]=0; 35 while(m--){ 36 scanf("%d%d%d",&u,&v,&w); 37 u--,v--; 38 map[u][v]=map[v][u]=min(map[u][v],w); 39 } 40 ans=inf; 41 for(int i=0;i<State[n];i++){ 42 bool flag=true; 43 for(int j=0;j<n;j++){ 44 if(visited[i][j]==0)flag=false;//是否每个城市都至少走了1次 45 if(dp[i][j]==inf)continue; 46 for(int k=0;k<n;k++)if(j!=k){ 47 if(visited[i][k]>=2)continue; 48 if(map[j][k]==inf)continue; 49 dp[i+State[k]][k]=min(dp[i+State[k]][k],dp[i][j]+map[j][k]); 50 } 51 } 52 if(flag){ 53 for(int j=0;j<n;j++){ 54 ans=min(ans,dp[i][j]); 55 } 56 } 57 } 58 if(ans==inf)ans=-1; 59 printf("%d\n",ans); 60 } 61 return 0; 62 } 63 64 65 66 67 68