poj2411 Mondriaan's Dream(轮廓线动态规划)
2015-03-23 00:35
417 查看
【题解】
首先将棋盘转化成"竖长形"(m<=n),然后从上往下逐行推进、每行从左往右枚举放骨牌的格子(规定骨牌只能往上、左两个方向放,不会影响到尚未枚举的格子)
那么正枚举的当前行可能是参差不齐的,在当前行产生轮廓(用1/0表示当前是否被覆盖,若当前格选择填0,其上方相邻位必为1,否则再无法被覆盖)
以枚举格的坐标和当前行的"轮廓"为状态,即:
d[cur][k]:棋盘第cur个格在状态为k时的方案数
其中,棋盘格位置(i,j)用cur来代替(相当于d[i][j][k],而d[i][j][k]只与(i,j-1)有关,因此采用滚动数组)
k是一个m位的二进制数,利用状压来表示(i,j-1),(i,j-2),…,(i,1),(i-1,m),(i-1,m-1),…,(i-1,j)是否被覆盖,这确定了一个封闭轮廓,记为"Km,…K2,K1"
(i,j)有三种决策:
不放骨牌:(i-1,j)必须有骨牌(Km==1),状态:1,…,K2,K1 (对(i,j)来说) -> K(m-1)…K2,K1,0 (对(i,j+1)或j==m时(i+1,1)来说)
放朝上的骨牌:(i-1,j)必须无骨牌(i!=1&&Km==0),状态:0,K(m-1),…,K2,K1 -> K(m-1)…K2,K1,1
放朝左的骨牌:(i-1,j)必须有骨牌,(i,j-1)必须无骨牌(j!=1&&Km==1&&K1==0),状态:1,K(m-1),…,K2,0 -> K(m-1)…K2,1,1
【代码】
首先将棋盘转化成"竖长形"(m<=n),然后从上往下逐行推进、每行从左往右枚举放骨牌的格子(规定骨牌只能往上、左两个方向放,不会影响到尚未枚举的格子)
那么正枚举的当前行可能是参差不齐的,在当前行产生轮廓(用1/0表示当前是否被覆盖,若当前格选择填0,其上方相邻位必为1,否则再无法被覆盖)
以枚举格的坐标和当前行的"轮廓"为状态,即:
d[cur][k]:棋盘第cur个格在状态为k时的方案数
其中,棋盘格位置(i,j)用cur来代替(相当于d[i][j][k],而d[i][j][k]只与(i,j-1)有关,因此采用滚动数组)
k是一个m位的二进制数,利用状压来表示(i,j-1),(i,j-2),…,(i,1),(i-1,m),(i-1,m-1),…,(i-1,j)是否被覆盖,这确定了一个封闭轮廓,记为"Km,…K2,K1"
(i,j)有三种决策:
不放骨牌:(i-1,j)必须有骨牌(Km==1),状态:1,…,K2,K1 (对(i,j)来说) -> K(m-1)…K2,K1,0 (对(i,j+1)或j==m时(i+1,1)来说)
放朝上的骨牌:(i-1,j)必须无骨牌(i!=1&&Km==0),状态:0,K(m-1),…,K2,K1 -> K(m-1)…K2,K1,1
放朝左的骨牌:(i-1,j)必须有骨牌,(i,j-1)必须无骨牌(j!=1&&Km==1&&K1==0),状态:1,K(m-1),…,K2,0 -> K(m-1)…K2,1,1
【代码】
#include<stdio.h> #include<stdlib.h> #include<string.h> long long d[2][4000]={0}; void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } int main() { int n,m,i,j,k,cur; while(scanf("%d%d",&n,&m)==2&&n!=0) { if(n<m) jh(&n,&m); cur=0; d[0][(1<<m)-1]=1;/*为什么其他的d[0][k]不用赋0:若k的二进制位Ki为0,则d[0][k]只对(1,Ki)上放朝上的骨牌起作用, 但第一行不能选择"放朝上的骨牌",因此d[1]["Ki朝上放骨牌对应的状态"]并未被改变,还是0,当然也不会影响接下来的几行*/ for(i=1;i<=n;i++) for(j=1;j<=m;j++) { cur^=1; memset(d[cur],0,sizeof(d[cur])); for(k=0;k<(1<<m);k++) { if( k&(1<<m-1) ) d[cur][(k<<1)^(1<<m)]+=d[1-cur][k];//不放骨牌 if( i!=1 && (k&(1<<m-1))==0 ) d[cur][(k<<1)+1]+=d[1-cur][k];//放朝上的骨牌 if( j!=1 && (k&(1<<m-1)) && (k&1)==0 ) d[cur][(k<<1)^(1<<m)+3]+=d[1-cur][k];//放朝左的骨牌 } } printf("%lld\n",d[cur][(1<<m)-1]); } return 0; }
相关文章推荐
- poj 2411 Mondriaan's Dream 轮廓线dp
- POJ 2411 Mondriaan's Dream 轮廓线DP
- POJ-2411 Mondriaan's Dream 状态压缩DP
- POJ 2411 Mondriaan's Dream 状态压缩dp
- POJ 2411 Mondriaan's Dream (状压DP)
- POJ 2411 Mondriaan's Dream 状态压缩DP
- poj 2411 Mondriaan's Dream_状态压缩dp
- poj 2411 Mondriaan's Dream 【dp】
- POJ 2411 Mondriaan's Dream (状压+dfs)
- poj 2411 Mondriaan's Dream(状压DP)
- poj 2411 && zoj 1100 Mondriaan's Dream ———状态压缩dp
- poj 2411 Mondriaan's Dream 状态压缩DP
- poj2411 Mondriaan's Dream 插头dp做法
- [动态规划]Pku2411--Mondriaan's Dream
- POJ 2411 Mondriaan's Dream 状态压缩DP
- POJ 2411 Mondriaan's Dream(状压 dp)
- poj 2411/hdu 1400 Mondriaan's Dream 状态压缩dp
- poj 2411 Mondriaan's Dream 状压dp入门
- HDOJ 1400 & POJ 2411 - Mondriaan's Dream 状态压缩DP
- POJ 2411 Mondriaan&#39;s Dream