标签:different 情况 cstring rect des 状压 cto using 方案
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 20822 | Accepted: 11732 |
Description
Input
Output
Sample Input
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
Sample Output
1 0 1 2 3 5 144 51205
Source
题意:
给定一个h*w的矩形。将矩形划分成1*2的小格子,有多少种方案。
思路:
考虑用行数作为状态,但是转移下一行时需要上一行的划分状态。
所以我们多开一维用于记录状态。用一个整数表示。第k位是1表示第i行第k列的格子是一个竖着的1*2长方形的上半部分。
那么对于第i+1行的状态j, j&k=0表示没有两个相邻行的相同列的格子都是长方形的上半部分。
j|k的二进制表示中,每一段连续的0都是偶数个。j|k是0的位,要么是j和k该位都是0说明这是一个横着的矩形。
只有这两种情况都满足时,(i, k)才能转移到(i+1, j)。
最后一行要输出的应该是没有一个1的情况。
注意要使用long long
1 //#include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<vector> 8 #include<map> 9 #include<set> 10 11 #define inf 0x3f3f3f3f 12 using namespace std; 13 typedef long long LL; 14 15 int h, w; 16 const int maxn = 1 << 12; 17 bool in_s[maxn]; 18 long long dp[12][maxn]; 19 20 int main(){ 21 while(scanf("%d%d", &h, &w) != EOF && (h || w)){ 22 for(int i = 0; i < 1 << w; i++){ 23 bool cnt = 0, has_odd = 0; 24 for(int j = 0; j < w; j++){ 25 if(i >> j & 1) has_odd |= cnt, cnt = 0; 26 else cnt ^= 1; 27 } 28 in_s[i] = has_odd | cnt ? 0 : 1; 29 } 30 31 //memset(dp, 0, sizeof(dp)); 32 dp[0][0] = 1; 33 for(int i = 1; i <= h; i++){ 34 for(int j = 0; j < 1 << w; j++){ 35 dp[i][j] = 0; 36 for(int k = 0; k < 1 << w; k++){ 37 if((k & j) == 0 && in_s[k | j]){ 38 dp[i][j] += dp[i - 1][k]; 39 } 40 } 41 } 42 } 43 printf("%lld\n", dp[h][0]); 44 } 45 return 0; 46 }
poj2411 Mondriaan's Dream【状压DP】
标签:different 情况 cstring rect des 状压 cto using 方案
原文地址:https://www.cnblogs.com/wyboooo/p/9783142.html