codeforces 111C(状压DP)

思路:数据范围很小,考虑用状压来做...这类网格放东西问题其实dp大概都可做。

  把问题转化为蜘蛛移动后,每个点上下左右和本身至少有一个网格有蜘蛛。

  首先取n,m的较小值作为列数,较大值作为行数,对每行进行状压(即用一个二进制数表示),0表示没有蜘蛛,1表示有蜘蛛。

  用dp[i][j][k]表示当前处理第i行,且第i行状态为j,第i+1行状态为k时,前i行的空网格数。

  那么只要逐行枚举j:0~(1<<(m-1)) - 1,k:0~(1<<(m-1)) - 1,再枚举i+2行的状态L:0~(1<<(m-1)) - 1

  然后检查第i+1行的可行性,(若发现某个位置自己和上下左右五个网格均无蜘蛛则不可行),DP转移方程:

  dp[i+1][k][L] = max(dp[i+1][k][L],dp[i][j][k] + Get(k));    其实:Get(k)就是获取k的二进制中有多少位为0。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define MP(a,b) make_pair(a,b)
21 
22 typedef long long ll;
23 typedef pair<int,int> pii;
24 const int INF = (1 << 30) - 1;
25 
26 int n,m,ans,top;
27 int dp[45][100][100];
28 
29 bool Check(int j,int k,int l){
30     int a,b,c,d,e;
31     FOR(i,0,n - 1){
32         a = j & (1 << i);
33         b = k & (1 << i);
34         c = l & (1 << i);
35         d = (i == 0) ? 0 : (k & (1 << (i - 1)));
36         e = (i == n - 1) ? 0 : (k & (1 << (i + 1)));
37         if(!(a || b || c || d || e)) return false;
38     }
39     return true;
40 }
41 
42 int Get(int v){
43     int cnt = 0;
44     FOR(i,0,n - 1) cnt += !(v & (1 << i));
45     return cnt;
46 }
47 
48 int main(){
49     scanf("%d%d",&n,&m);
50     if(n > m) swap(n,m);
51     top = (1 << n) - 1;
52     FOR(i,0,top) FOR(j,0,top) dp[0][i][j] = -INF;
53     FOR(i,0,top){
54         dp[0][0][i] = 0;
55     }
56     FOR(i,0,m){
57         FOR(j,0,top) FOR(k,0,top) FOR(l,0,top){
58             if(Check(j,k,l)){
59                 dp[i + 1][k][l] = max(dp[i + 1][k][l],
60                         dp[i][j][k] + Get(k));
61                 //printf("dp[%d][%d][%d]:%d -> %d\n",i,j,k,dp[i][j][k],l);
62             }
63         }
64     }
65     FOR(i,0,top) ans = max(ans,dp[m][i][0]);
66     printf("%d\n",ans);
67     return 0;
68 }

 

posted @ 2015-01-29 23:06  Naturain  阅读(207)  评论(0编辑  收藏  举报