[状态压缩DP] COJ 1129 送货到家

第一道状态压缩DP;

这道题要求一个无向图的最小权回路,要求经过所有点,所以可以任选一个点(这里选0)作为起点,以后的状态f[s, i]表示从0出发到i结束的最小权路径,最终求得f[1<<n-1, k]后要加上w[0, k],然后求最小值:

for k = 0:n-1

  ans = min(f[1<<n-1, k]+w[0, k]);

print(ans);

 1 # include <cstdio>
 2 # include <cstring>
 3  
 4 # define N 15
 5 # define INF 0X1FFFFFFF
 6  
 7 int n;
 8 int f[1<<N][N];
 9 int w[N][N];
10  
11 int min(int x, int y)
12 {
13     return x<y ? x:y;
14 }
15 
16 void print(int n, int s)
17 {
18     for (int i = n-1; i >= 0; --i)
19     {
20         printf((s>>i)&0x1 ? "1":"0");
21     }
22 }
23  
24 int dp(int s, int j)
25 {
26     int &ans = f[s][j];
27     if (ans != -1) return ans;
28     if ((s&(~(1<<j))) == 1) return ans = w[0][j];
29     ans = INF;
30     for (int k = 1; k < n; ++k) if (k!=j && ((s>>k)&0x1))
31     {
32         ans = min(ans, dp(s&(~(1<<j)), k)+w[k][j]);
33     }
34     return ans;
35 }
36  
37 void solve(void)
38 {
39     int ans = INF;
40     //if (n==0){puts("NoAnswer");return;}
41    // if (n==1){puts("0");return;}
42     for (int i = 0; i < (1<<n); ++i)
43         memset(f[i], -1, sizeof(int)*n);
44   
45     f[1][0] = 0;
46     for (int i = 0; i < n; ++i)
47     {
48         ans = min(ans, dp((1<<n)-1, i)+w[0][i]);
49     }    
50     if (ans < INF)
51         printf("%d\n", ans);
52     else
53         printf("NoAnswer\n");
54 }
55  
56 void read_graph(void)
57 {
58     for (int i = 0; i < n; ++i)
59     for (int j = 0; j < n; ++j)
60     {
61         scanf("%d", &w[i][j]);
62         if (w[i][j] == 0 && i!=j)
63             w[j][i] = w[i][j] = INF;
64         else w[j][i] = w[i][j];
65     }      
66 }
67  
68 int main()
69 {
70     while (~scanf("%d", &n))
71     {
72         read_graph();
73         solve();
74     }
75      
76     return 0;
77 }

涉及位运算,多加几个括号,避免出现优先级导致的问题。

原文地址:https://www.cnblogs.com/JMDWQ/p/2623610.html