[状态压缩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 }

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

你可能感兴趣的:(压缩)