Vijos 1456 最小总代价(状态压缩DP)
用二维数组表示,第一维表示状态,第二维表示此状态最后一个专递者。
状态转移为 if((~que1[j])&(1<<u))//开始这个判断想错了,一直RE。。。对位运算不熟啊。。
dp[que1[j]+(1<<u)][u] = min(dp[que1[j]+(1<<u)][u],dp[que1[j]][k]+p[k+1][u+1]);
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <string> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 int p[20][20]; 8 int dp[500000][17]; 9 int que1[500000],que2[500000]; 10 int o[500000]; 11 int main() 12 { 13 int n,i,j,k,u,num,t; 14 scanf("%d",&n); 15 for(i = 1; i <= n; i ++) 16 { 17 for(j = 1; j <= n; j ++) 18 scanf("%d",&p[i][j]); 19 } 20 for(i = 0; i < 1<<n; i ++) 21 { 22 for(j = 0; j < n; j ++) 23 { 24 dp[i][j] = INF; 25 } 26 } 27 num = 0; 28 for(i = 0; i < n;i ++) 29 { 30 dp[1<<i][i] = 0; 31 que1[num++] = 1<<i; 32 } 33 for(i = 2;i <= n;i ++) 34 { 35 t = 0; 36 for(j = 0;j < num;j ++) 37 { 38 for(k = 0;k < n;k ++) 39 { 40 for(u = 0;u < n;u ++) 41 { 42 if(k != u) 43 { 44 if((~que1[j])&(1<<u)) 45 { 46 dp[que1[j]+(1<<u)][u] = min(dp[que1[j]+(1<<u)][u],dp[que1[j]][k]+p[k+1][u+1]); 47 if(!o[que1[j]+(1<<u)]) 48 { 49 o[que1[j]+(1<<u)] = 1; 50 que2[t++] = que1[j]+(1<<u); 51 } 52 } 53 } 54 } 55 } 56 } 57 num = t; 58 for(j = 0;j < num;j ++) 59 { 60 que1[j] = que2[j]; 61 que2[j] = 0; 62 } 63 } 64 int ans = INF; 65 for(i = 0;i < n;i ++) 66 ans = min(dp[(1<<n)-1][i],ans); 67 printf("%d\n",ans); 68 return 0; 69 } 70 /* 71 16 72 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 73 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 74 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 75 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 76 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 77 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 78 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 79 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 80 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 81 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 82 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 83 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 84 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 85 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 86 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 87 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 88 */