POJ - 2411
题意:给你一个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\n",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\n", dp[cur][up - 1]); 45 } 46 return 0; 47 } 48 /* 49 */