# HDU 1565 方格取数(1)

状压dp，dp[i][j]：表示到第i行，当前状态为s的最大值。预处理在每一行选的时候可能的状态，及这个状态的价值。

转移方程：dp[i][j] = max(dp[i][j],dp[i-1][k]+sum[i][j]) k与j不冲突。

``` 1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<iostream>
5
6 using namespace std;
7
8 int sta[20010],dp[22][20010],sum[22][20010],a[22][22];
9 int n,tot;
10
11
13     int x = 0,f = 1;char ch = getchar();
14     for (; !isdigit(ch); ch=getchar()) if(ch==‘-‘) f=-1;
15     for (; isdigit(ch); ch=getchar()) x = x*10+ch-‘0‘;
16     return x * f;
17 }
18 void init() {
19     tot = 0;
20     memset(dp,0,sizeof(dp));
21     memset(sum,0,sizeof(sum));
22     memset(sta,0,sizeof(sta));
23     for (int i=1; i<=n; ++i)
24         for (int j=1; j<=n; ++j)
26
27 }
28 void getsta() {
29     int t = (1 << n) - 1;
30     for (int i=0; i<=t; ++i) {
31         if (i & (i << 1) ) continue;
32         sta[++tot] = i;
33     }
34 }
35 void getsum() {
36     for (int i=1; i<=n; ++i) {
37         for (int j=1; j<=tot; ++j) {
38             for (int k=0; k<n; ++k) {
39                 sum[i][j] += ((1<<k)&sta[j])?a[i][n-k]:0;
40             }
41         }
42     }
43 }
44 void getdp() {
45     for (int i=1; i<=tot; ++i) dp[1][i] = sum[1][i];
46     for (int i=2; i<=n; ++i) {
47         for (int j=1; j<=tot; ++j) {
48         for (int k=1; k<=tot; ++k) {
49                 if (sta[j] & sta[k]) continue;
50                 dp[i][j] = max(dp[i][j],dp[i-1][k]+sum[i][j]);
51             }
52         }
53     }
54 }
55 void getans() {
56     int ans = 0;
57     for (int i=1; i<=tot; ++i)
58         ans = max(dp[n][i],ans);
59     cout << ans << "\n";
60 }
61 int main() {
62     while (scanf("%d",&n) != EOF) {
63         init();
64         getsta();
65         getsum();
66         getdp();
67         getans();
68     }
69     return 0;
70 }```

HDU 1565 方格取数(1)

(0)
(0)