HDU 4539 郑厂长系列故事――排兵布阵 状压dp

题目链接:

https://vjudge.net/contest/159644#problem/H

题意:

注意 是曼哈顿距离恰好是2,恰好!!!

题解:

与poj1185差不多的…
滚动数组,否则MLE,是我MLE了…

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16 const int maxn = 1e5+10;
17 
18 ll dp[2][1005][1005];
19 int num[1005],cur[105];
20 int n,m,cnt;
21 int sta[1005];
22 
23 int getnum(int x){
24     int res = 0;
25     while(x){
26         if(x & 1) res++;
27         x >>= 1;
28     }
29     return res;
30 }
31 
32 void init(){
33     cnt = 0;
34     for(int i=0; i<=(1<<10); i++){
35         if(!(i & (i<<2))){
36             sta[cnt] = i;
37             num[cnt] = getnum(i);
38             cnt++;
39         }
40     }
41 }
42 
43 int main(){
44     init();
45     while(cin>>n>>m){
46         MS(cur);
47         for(int i=0; i<n; i++)
48             for(int j=0; j<m; j++){
49                 int x; cin >> x;
50                 if(x == 1) cur[i] += (1<<j);
51             }
52         memset(dp,-1,sizeof(dp));
53         int now=0,pre=1;
54         for(int i=0; i<cnt; i++){
55             if(!(sta[i]&(~cur[0])))
56                 dp[now][i][0] = num[i]; 
57         }
58 
59         for(int i=1; i<n; i++){
60             swap(now,pre);
61             for(int j=0; j<cnt; j++){
62                 if(sta[j]&(~cur[i])) continue;
63                 for(int k=0; k<cnt; k++){
64                     if(sta[k]&(~cur[i-1])) continue;
65                     if(((sta[j]<<1)&sta[k]) || ((sta[j]>>1)&sta[k])) continue;
66                     for(int x=0; x<cnt; x++){
67                         if(i>=2 && (sta[x]&(~cur[i-2]))) continue;
68                         if(sta[j]&sta[x]) continue;
69                         if(dp[pre][k][x] == -1) continue;
70                         dp[now][j][k] = max(dp[now][j][k],dp[pre][k][x]+num[j]);
71                     }
72                 }
73             }
74         }
75 
76         ll ans = 0;
77         for(int i=0; i<cnt; i++)
78             for(int j=0; j<cnt; j++)
79                 ans = max(ans,dp[now][i][j]);
80 
81         cout << ans << endl;
82     }
83 
84     return 0;
85 }
原文地址:https://www.cnblogs.com/yxg123123/p/6827554.html