POJ

题意:给你一个n行m列的格子,问你放1*2的木块有多少种放法。

思路:dp[i][s] 表示到第i行状态为s的方法数。 状态0表示这个位置是被下面那个竖着放的木块占了的,状态1表示是当前行横着放占了的。

暴力打出所有的匹配,然后状态转移就好啦,好像也能用轮廓线dp做,这个不会,明天补吧。。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #define fi first
 5 #define se second
 6 #define mk make_pair
 7 #define pii pair<int,int>
 8 #define read(x) scanf("%d",&x)
 9 #define sread(x) scanf("%s",x)
10 #define dread(x) scanf("%lf",&x)
11 #define lread(x) scanf("%lld",&x)
12 using namespace std;
13 
14 typedef long long ll;
15 const int inf=0x3f3f3f3f;
16 const int INF=0x3f3f3f3f3f3f3f3f;
17 const int N=11;
18 const int M=12;
19 
20 int n,m,up;
21 ll dp[M][1<<N];
22 vector<int> s[1<<N];
23 
24 bool check(int s1,int s2)
25 {
26     if((s1|s2)!=up-1)
27         return false;
28     int cnt=0,all=n;
29     while(all--)
30     {
31         if(s2&1 && s1&1)
32             cnt++;
33         else
34         {
35             if(cnt&1)
36                 return false;
37             cnt=0;
38         }
39         s2>>=1; s1>>=1;
40     }
41     if(cnt&1)
42         return false;
43     return true;
44 }
45 void init(){
46     if(m>n) swap(n,m);
47     up=1<<m;
48 
49     memset(dp,0,sizeof(dp));
50     for(int i=0;i<up;i++)
51         s[i].clear();
52 
53     for(int i=0;i<up;i++)
54         for(int j=0;j<up;j++)
55             if(check(i,j))
56                 s[i].push_back(j);
57 }
58 int main()
59 {
60     while(scanf("%d%d",&n,&m)!=EOF && n && m)
61     {
62         init();
63 
64         dp[0][up-1]=1;
65         for(int i=0;i<n;i++)
66         {
67             for(int j=0;j<up;j++)
68             {
69                 if(!dp[i][j])
70                     continue;
71 
72                 for(int u=0;u<s[j].size();u++)
73                 {
74                     int k=s[j][u];
75                     dp[i+1][k]+=dp[i][j];
76                 }
77             }
78         }
79         printf("%lld
",dp[n][up-1]);
80     }
81     return 0;
82 }
83 /*
84 */

终于会一点轮廓线啦!!!

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define LL long long
 5 #define fi first
 6 #define se second
 7 #define mk make_pair
 8 #define pii pair<int,int>
 9 #define piii pair<int, pair<int,int>>
10 
11 using namespace std;
12 
13 const int N = 1e5 + 7;
14 const int M = 1e4 + 7;
15 const int inf = 0x3f3f3f3f;
16 const LL INF = 0x3f3f3f3f3f3f3f3f;
17 const int mod = 1e9 + 7;
18 const double eps = 1e-10;
19 //const double PI = acos(-1);
20 
21 int n, m, up, cur;
22 LL dp[2][1 << 11];
23 void update(int a, int b) {
24     if(b & (1 << m)) dp[cur][b ^ (1 << m)] += dp[1 - cur][a];
25 }
26 int main() {
27     while(scanf("%d%d", &n, &m) != EOF && n && m) {
28         if(n < m) swap(n, m);
29         memset(dp, 0, sizeof(dp));
30         up = 1 << m; cur = 0;
31         dp[0][(1 << m) - 1] = 1;
32         for(int i = 0; i < n; i++) {
33             for(int j = 0; j < m; j++) {
34                 cur ^= 1;
35                 memset(dp[cur], 0, sizeof(dp[cur]));
36                 for(int s = 0; s < up; s++) {
37                     update(s, s << 1);
38                     if(i && !(s & (1 << m - 1)))
39                         update(s, (s << 1) ^ (1 << m) ^ 1);
40                     if(j && !(s & 1)) update(s, (s << 1) ^ 3);
41                 }
42             }
43         }
44         printf("%lld
", dp[cur][up - 1]);
45     }
46     return 0;
47 }
48 /*
49 */
原文地址:https://www.cnblogs.com/CJLHY/p/8537116.html