标签:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 15407 | Accepted: 8889 |
Description
Input
Output
Sample Input
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
Sample Output
1 0 1 2 3 5 144 51205
大意:h,w分别为一个矩形的长和宽(h,m<=11),问用1*2的小矩形(可横竖摆放),问一共有多少种方法。
状态压缩,竖着摆放的小矩形占据该行的该位置和上一行对应位置,0表示该位置不摆放(即下一行竖着摆放的小矩形占据这个位置),1表示该位置摆放(横或竖)
dfs(l+2,now<<2|3,pre<<2|3); 上下两行横着摆放 dfs(l+1,now<<1|1,pre<<1); 当前行竖着摆放,并占据上一行对应位置 dfs(l+1,now<<1,pre<<1|1); 上一行对应位置无论如何被占据,当前行由下一行竖着摆放的矩形占据
dfs搜出所有可能的路径path[num][2];path[i][0]存第i条路的当前状态,path[i][1]存第i条路的上一行状态。
剩下的dp很常规。
#include<iostream> #include<cstring> #include<queue> #include<cstdio> #include<map> #include<algorithm> using namespace std; #define LL long long int path[14000][2]; LL dp[15][2<<11]; int h,w,num; void dfs(int l,int now,int pre) { if(l>w) return; if(l==w) { path[num][0]=now; path[num++][1]=pre; return; } dfs(l+2,now<<2|3,pre<<2|3); dfs(l+1,now<<1|1,pre<<1); dfs(l+1,now<<1,pre<<1|1); } int main() { while(scanf("%d%d",&h,&w)!=EOF&&h+w) { num=0; dfs(0,0,0); memset(dp,0,sizeof(dp)); dp[0][(1<<w)-1]=1; for(int i=0;i<h;i++) for(int j=0;j<num;j++) dp[i+1][path[j][0]]+=dp[i][path[j][1]]; printf("%I64d\n",dp[h][(1<<w)-1]); } return 0; }
POJ_2411_Mondriaan's Dream_状态压缩dp
标签:
原文地址:http://www.cnblogs.com/jasonlixuetao/p/5776666.html