zoukankan      html  css  js  c++  java
  • POJ 2411.Mondriaan's Dream 解题报告

    题意:

          给出n*m (1≤n、m≤11)的方格棋盘,用1*2的长方形骨牌不重叠地覆盖这个棋盘,求覆盖满的方案数。


    Solution:

                   位运算+状态压缩+dp

                   二进制数(####)代表填完一行后这一行的状态,填满的地方为1,未填的地方为0。

                   显然在填第i行时,能改变的仅为第i-1行和第i行,因此要满足在填第i行时,第1~i-2行已经全部填满。

                   DFS一行的状态,要是填完第i行时,第i-1行被填满。

                   因此两行的状态(p1,p2)满足,~p1=p2;

                  

                   DFS出所有满足条件的状态对(P1,P2)

                   ①第i行第k位为1,第i-1行第k位为0。(一块骨牌竖直放置)

                             dfs(k+1,last<<1,now<<1 | 1)

                   ②第i行第k位为0,第i-1行第k位为1。 (第i行空出第k位)

                             dfs(k+1,last<<1 | 1,now<<1)

                   ③骨牌横向放置。

                            bfs (k + 2, last << 2 | 3, now << 2 | 3)

                   

                   转移方程:F[i][sp1]=∑f[i-1][sp2]

    代码:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define LL long long
    using namespace std;
    int n, m, x;
    LL f[12][1 << 12];
    void dfs (int k, int last, int now) {
    	if (k ==m )     f[x][now] += f[x - 1][last];
    	if (k > m) return;
    	dfs (k + 1, last << 1, now << 1 | 1);
    	dfs (k + 1, last << 1 | 1, now << 1);
    	dfs (k + 2, last << 2 | 3, now << 2 | 3);
    }
    int main() {
    	while (~scanf ("%d %d", &n, &m) ) {
    		if (n == 0) break;
    		if (n > m)  swap (n, m);
    		memset (f, 0, sizeof f);
    		f[0][ (1 << m) - 1] = 1;
    		for (x = 1; x <= n; x++)
    			dfs (0, 0, 0);
    		printf ("%lld
    ", f[n][ (1 << m) - 1]);
    	}
    }
    

      

  • 相关阅读:
    单例和工厂设计模式
    EFCore中如何移除主外键关系
    使用.Net Core实现FNV分布式hash一致性算法
    我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
    FNV哈希算法
    AspNetCore中基于Session的身份验证
    详解Microsoft.AspNetCore.CookiePolicy
    理解cookies
    详解Asp.Net Core中的Cookies
    5. 安装Dashboard UI、heapster
  • 原文地址:https://www.cnblogs.com/keam37/p/3834490.html
Copyright © 2011-2022 走看看