poj 2411 Mondriaan's Dream

来源:互联网 发布:js怎么创建二维数组 编辑:程序博客网 时间:2024/06/06 17:17

点击打开链接

反思:每个格子用1 标记已放东西,用0标记暂且没有放东西;

枚举状态 x 从0 到 1<<m  dfs 相对应的状态 y ; cnt[x][y]=1 表示x到y状态是合法的;

dp初始: 第一行一开始肯定是要全是空的; 所以只有dp[0][0] =1;

第i行是由第i-1行 推下来, 如果cnt[x][y]成立 dp[i][y] += dp[i-1][x];

最后:要的是全部铺满;意味着 第n+1行的状态全为空   ans=dp[n+1][0];

为什么ans!= dp[n][ 1<<m] 呢? 因为,全为1 只是代表 当前要全放 (n-1行 与 n行 全是放着2*1 的竖的 ),并不是全放满!

#include<stdio.h>#include<string.h>#include<math.h>#include<string>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<list>#include<map>#include<set>using namespace std;const int N=11;int n,m;long long dp[N+2][1<<N];int cnt[1<<N][1<<N];void dfs(int x,int y,int dep){   if(dep>=m) {       cnt[x][y]++;       return;   }    int t1=(x>>dep)&1;    if(dep==m-1){        if(t1) dfs(x,y,dep+1);        else dfs(x,y+(1<<dep),dep+1);        return;    }    int t2=(x>>(dep+1))&1;    if(t1==0 && t2==0) {        dfs(x,y,dep+2); //横放一块儿1*2 ;        dfs(x,y+(1<<dep),dep+1); // 竖着放一块儿;    }    if(t1==0 && t2) dfs(x, y+(1<<dep),dep+2);    if(t1) dfs(x,y,dep+1);}long long  deal(){    if((n*m)%2) return 0;    memset(cnt,0,sizeof(cnt));    int all=1<<m;    for(int x=0;x<all;x++)        dfs(x,0,0);    memset(dp,0,sizeof(dp));//    for(int x=0;x<all;x++){//           dp[0][x]=cnt[all-1][x];//           printf("dp=%d\n",dp[0][x]);  //处理第一行;并找出合理的状态;发现其实就是dp[0][0]=1;//    }    dp[0][0]=1; //初始第一行;    for(int i=1;i<=n;i++){        for(int x=0;x<all;x++) if(dp[i-1][x])           for(int y=0;y<all;y++) if(cnt[x][y])             dp[i][y]+= dp[i-1][x];    }    return dp[n][0];}int main(){//     freopen("in.in","r",stdin);     while(~scanf("%d%d",&n,&m)&&(n+m)){        if(n<m) swap(n,m);        cout << deal() << endl;     }     return 0;}




0 0
原创粉丝点击