POJ 3311 Hie with the Pie
第二道状态压缩。。。 自己做出来还是很爽的
二维, 第一维表示当前状态, 第二维表示当前地点。
先从未达到tt这个点的状态推出当前有tt状态的点,然后再根据同状态其他已到达点 试着从其他点更新到该点,使得时间更小。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int map[12][12], dp[1333][11], p[12]; const int INF=1<<29; void init() { int i, k=1; p[0]=0; for(i=1;i<=1024;i*=2) { p[i]=k++; } } int main() { int n, i, j, k, r, num, tt; init(); while(scanf("%d",&n)!=EOF) { if(n==0) break; for(i=0; i<=n; i++) for(j=0; j<=n; j++) scanf("%d",&map[i][j]); num=1<<n; for(i=0; i<=num; i++) for(j=0; j<=n; j++) dp[i][j]=INF; for(i=0; i<=n; i++) dp[0][i]=map[0][i]; for(i=1; i<num; i++) { for(j=i; j>0; j-=j&(-j)) { tt=j&(-j); for(r=0; r<=n; r++) { dp[i][p[tt]]=min(dp[i][p[tt]],dp[i^tt][r]+map[r][p[tt]]); } } for(j=0; j<=n; j++) { for(k=0; k<=n; k++) dp[i][j]=min(dp[i][j],dp[i][k]+map[k][j]); } } int ans=INF; for(i=0; i<=n; i++) { ans=min(ans,dp[num-1][i]+map[i][0]); } printf("%d\n",ans); } return 0; }