状态压缩-覆盖问题-poj 2411 2663

来源:互联网 发布:python try statement 编辑:程序博客网 时间:2024/06/10 03:26

poj2411-Mondriaan's Dream
题目大意
用1*2的骨牌覆盖n*m的棋盘,问有多少种方案。可以旋转90°放。不能覆盖则输出0。


解题思路
用 f【i,s】表示 把前 i-1 行覆盖满、第 i 行覆盖状态为 s 的覆盖方案数。因为在第 i 行上放置的骨牌多也只能影响到第 i-1 行(竖着放的时候是占用当前行和上一行),因此要满足在填第i行时,第1~i-2行已经全部填满,所以DFS一行的状态,要使得填完(不一定填满)第i行时,第i-1行被填满。则容易得递推式:
 f[i][s] += f[i-1][s2]      f[0][1<<m-1]=1;
然后就是处理如何dfs的问题。参数:列p,当前行的状态now,上一行的状态last。那么有三种操作
①竖放:dfs(p+1,(now<<1)|1,last<<1) ; //竖放(占据当前行和上一行),在当前行竖放需要上一行的p+1列是空的
②横放:dfs(p+2,(now<<2)|3,(last<<2)|3) ; //横放:上一行当前列没有空位,没办法竖放
③不放:dfs(p+1,(now<<1),(last<<1)|1); //不放 : 前一行的p+1列没有空位,就不能放
(注*  以①为例,表示当前行在p+1列的时候,状态为(now<<1)|1,上一行状态为last<<1,与之前不同的是这次是从左往右找列,也就是走到下一列就让前面的向左移,腾出一个未定义的列使用)

代码
#include <cstring>#include <iostream>#include <algorithm>#include <cstdio>using namespace std;int n,m,row;long long f[12][1<<12];//这里要开longlongvoid dfs(int p,int now,int last){    if(p>m) return ;    if(p==m)//到达最后一列了    {        f[row][now] += f[row-1][last];    }    dfs(p+1,(now<<1),(last<<1)|1); //不放 : 前一行的p+1列没有空位,就不能放    dfs(p+1,(now<<1)|1,last<<1);//竖放(占据当前行和上一行),在当前行竖放需要上一行的p+1列是空的    dfs(p+2,(now<<2)|3,(last<<2)|3);//横放:上一行当前列没有空位,没办法竖放}int main(){    while(scanf("%d%d",&n,&m))//n行m列    {        if(n==0 && m==0) break;        if(n%2 && m%2)        {            printf("0\n");            continue;        }        if(n<m) swap(n,m);//让小的当列        memset(f,0,sizeof(f));        f[0][(1<<m)-1] = 1; //第0行全放满是一种方案        for(row=1;row<=n;++row)            dfs(0,0,0);      cout<<f[n][(1<<m)-1]<<endl;    }    return 0;}



poj 2663-Tri Tiling

题目大意
用1*2的骨牌覆盖3*n的棋盘,问有多少种方案

解题思路
这道题和上一道题没什么太大区别,就是把m变成3,还是和好写的

代码
#include <cstring>#include <iostream>#include <algorithm>#include <cstdio>using namespace std;int n;//n行3列int f[35][1<<3];int row;void dfs(int p,int now,int last){    if(p>3) return ;    if(p==3)    {        f[row][now] +=f[row-1][last];    }    else    {        dfs(p+1,now<<1,(last<<1)|1);//不放        dfs(p+2,(now<<2)|3,(last<<2)|3);//横放        dfs(p+1,(now<<1)|1,last<<1);    }}int main(){    while(scanf("%d",&n) && n !=-1)    {        if(n%2) {printf("0\n"); continue;}        memset(f,0,sizeof(f));        f[0][(1<<3)-1]=1;        for(row=1;row<=n;++row)        {            dfs(0,0,0);        }        cout<<f[n][(1<<3)-1]<<endl;    }    return 0;}




1 0
原创粉丝点击