POJ2663
来源:互联网 发布:淘宝买家好评率100% 编辑:程序博客网 时间:2024/06/06 02:12
POJ2663 Tri Tiling
现在给出一个3*n(0<=n<=30)的矩阵,要求用1*2的骨牌来填充,问有多少种填充方式?
分析:
解法一:
首先这道题n的规模比较小我先试下用轮廓线DP来解。
(轮廓线DP见:http://blog.csdn.net/u013480600/article/details/19499899)
注意POJ的这道题目测试数据当n==0时输出的是1,否则WA。
AC代码:47MS
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 15;long long d[2][1<<maxn];int n,m,cur;void update(int a,int b)//a是包含m位1进制数的老状态,b是包含m+1位1进制数的新状态{ if(b&(1<<m)) d[cur][b^(1<<m)] += d[1-cur][a];//只有新轮廓线首位为1时才更新}int main(){ while( scanf("%d",&n)==1&&n>=0 ) { //if(m>n)swap(n,m); m=3; memset(d,0,sizeof(d)); cur=0; d[cur][(1<<m)-1]=1; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cur ^=1; memset(d[cur],0,sizeof(d[cur])); for(int k=0;k<(1<<m);k++)//k的二进制形式表示前一个格子的轮廓线状态 { update(k,k<<1);//当前格不放,直接k左移一位就表示带m+1位的新轮廓线的状态 if(i && !(k&(1<<(m-1)) )) update(k,(k<<1)^(1<<m)^1);//上放,要求轮廓线首为0 if(j && (!(k&1)) ) update(k,(k<<1)^3);//左放,要求轮廓线尾0,首1 } } printf("%I64d\n",d[cur][(1<<m)-1]); } return 0;}
解法二:递推法。
由于本题的矩阵只有3列,所以可以推断出,该矩阵必定由且仅由3*2,3*4,…3*m(m为偶数)的不可分割的小矩阵构成。如下:
等等。还有2*6,2*8的矩阵没有画出来,可以自己想想如何构成不可分割的2*6小矩阵。且可以推断2*m(m>=4且为偶数)的不可分割小矩阵数目都是2.想想为什么?
所以可以得到计算a[n](表示3*n的矩阵有多少摆放方式)的递推公式:
a[n]=a[n-2]*3+a[n-4]*2+a[n-6]*2+….初始值为a[0]=1且其他a[n]初始时都为0。
AC代码:0MS
//利用递推的公式求解#include<cstdio>#include<cstring>using namespace std;const int maxn = 35;int n;long long a[maxn];int main(){ memset(a,0,sizeof(a)); a[0]=1; a[2]=3; for(int i=4;i<31;i+=2) { int j=4; a[i] +=a[i-2]*3; while(j<=i) { a[i]+=a[i-j]*2; j+=2; } } while(scanf("%d",&n)==1&&n>=0) { printf("%I64d\n",a[n]); } return 0;}
解法三:利用兼容模式队求解状态压缩DP。
(兼容模式状态压缩DP见:http://blog.csdn.net/u013480600/article/details/19569291)
直接把原题的m该成3,然后注意读入的格式即可。
AC代码:0ms
//兼容模式队求解状态压缩DP#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 35;//最大行数const int maxm = 16*16;//兼容模式对的最大数目int n,m,w;long long d[maxn][1<<4];int path[maxm][2];void dfs(int c,int pre,int now){ if(c>m)return ; else if(c==m) { path[w][0]=pre; path[w++][1]=now; return ; } dfs(c+1,(pre<<1)|1,now<<1);//不放 dfs(c+1,(pre<<1),(now<<1)|1);//上放 dfs(c+2,(pre<<2)|3,(now<<2)|3);//右放}int main(){ while(scanf("%d",&n)==1&&n>=0) { m=3; w=0; dfs(0,0,0); memset(d,0,sizeof(d)); d[0][(1<<m)-1]=1; for(int i=0;i<n;i++) for(int j=0;j<w;j++) d[i+1][path[j][1]] += d[i][path[j][0]]; printf("%I64d\n",d[n][(1<<m)-1]); } return 0;}
0 0
- POJ2663
- poj2663
- poj2663 分治
- poj2663 递推
- POJ2663 完美覆盖
- poj2663递推思想
- 递推POJ2663
- POJ2663——Tri Tiling
- poj2663 Tri Tiling dp 水题
- [POJ2663]Tri Tiling(dp)
- POJ2663(矩阵+递推)
- HDU 1143Tri Tiling&&POJ2663
- poj2663 Tri Tiling dp递推
- Poj1185&Poj2411 状压dp(from Poj2663)
- className.class.getResourceAsStream()与ClassLoader.getSystemResourceAsStream() 的区别
- <Win32_2>Bitmap位图应用1 ------ Win32的数字时钟
- hadoop机架感知
- 第六届中国云计算大会
- linux socket学习(二)
- POJ2663
- Cycript segmentation fault:11 错误 解决
- 说说Android 两种为自定义组件添加属性的使用方法和区别
- js去除空格,包括全角
- Android解析json数据(Gson)
- 详解并行逻辑回归
- 【安卓笔记】图片特效之底片效果
- 左右查询与内查询
- 冒泡排序的实现及优缺点