acmclub 1059 贴瓷砖

来源:互联网 发布:淘宝会员等级没有了 编辑:程序博客网 时间:2024/04/28 12:20

来源:http://zju.acmclub.com/index.php?app=problem_title&id=1&problem_id=1059



1059:贴瓷砖分数: 1

时间限制:1 秒
内存限制:32 兆
特殊判题: 否
提交:69
解决: 43

标签

  • 递推

题目描述

有一块大小是 2 * n 的墙面,现在需要用2种规格的瓷砖铺满,瓷砖规格分别是 2 * 1 和 2 * 2,请计算一共有多少种铺设的方法。

输入格式

输入的第一行包含一个正整数T(T<=20),表示一共有T组数据,接着是T行数据,每行包含一个正整数N(N<=30),表示墙面的大小是2行N列。

输出

输出一共有多少种铺设的方法,每组数据的输出占一行。

样例输入

3
2
8
12

样例输出

3
171
2731

提示[+]

*** 提示已隐藏,点击上方 [+] 可显示 ***



题意: 略。
题解:  开始直到是要用递推做,但就是不知道怎么找递推式~~ 于是傻傻的写了个dfs,不用说~~ 交上去就超时了。
【详解】

 

当n=1时,显然只有一种铺设方法。

n=2,可以用2个竖的3*1瓷砖铺设,也可以用1个竖的3*2瓷砖铺设,故共有两种铺设方案。

n=3

1) 用3个竖的3*1瓷砖铺设

2) 先用1个竖的3*1,再用1个竖的3*2瓷砖铺设

3) 先用1个竖的3*2,再用1个竖的3*1瓷砖铺设

4) 用13*3的瓷砖铺设

5) 用3个横的3*1瓷砖铺设

6) 先用1个横的3*1,再用一个横的3*2瓷砖铺设

7) 先用1个横的3*2,再用一个横的3*1瓷砖铺设

共7中方案 


那么推广到一般情况(n>4),记铺设3*n墙壁总方案数为f(n).

1) 如果先铺3*1的墙壁,铺设3*1的方案数为1,还剩下3*n-1)的墙壁的总方案数位为f(n-1),故这种情况共有有1*f(n-1)种方案

2) 如果先铺3*2的墙壁,铺设3*2的方案数为1(因为要去掉与1)中重复的情况),还剩下3*n-2)的墙壁的总方案数为f(n-2)故这种情况共有有1*f(n-2)种方案

3) 如果先铺3*3的墙壁,铺设3*3的方案数为4(去掉与(1),(2)重复的情况),还剩下3*n-3)的墙壁的总分数为f(n-3),故这种情况共有有4*f(n-3)种方案

所以可以得出递推式f(n)=f(n-1)+f(n-2)+4*f(n-3);(n>=4)


先贴上我超时的dfs代码(乱的不成样子了,估计也只有我自己知道什么意思):

#include<iostream>#include<cstring>using namespace std;int dir[2][3][2]={{{0,0},{1,0},{2,0}},{{0,0},{0,1},{0,2}}};int map[3][55],n,p=0,a[10];
long long count=0;void dfs(int x,int y,int step){if(x<0||x>=3||y<0||y>=n)return ;if(!step){count++;return ;}if(!map[x][y]){for(int i=0;i<5;i++){if(!i&&!x){bool flag=true;for(int j=0;j<3;j++)if(map[x+dir[i][j][0]][y+dir[i][j][1]])flag=false;if(flag){if(3==step){count++;return ;}for(int j=0;j<3;j++)map[x+dir[i][j][0]][y+dir[i][j][1]]=-1;if(x*y<2*(n-1)){int tempx=x,tempy=y+1;if(tempy>=n){tempx++;tempy=0;}dfs(tempx,tempy,step-3);}for(int j=0;j<3;j++)map[x+dir[i][j][0]][y+dir[i][j][1]]=0;}}if(i==1&&(y+2)<n){bool flag=true;for(int j=0;j<3;j++)if(map[x+dir[i][j][0]][y+dir[i][j][1]])flag=false;if(flag){if(3==step){count++;return ;}for(int j=0;j<3;j++)map[x+dir[i][j][0]][y+dir[i][j][1]]=-1;int tempx=x,tempy=y+3;if(tempy>=n){tempx++;tempy%=n;}if(tempx<3&&tempy*tempx<=2*(n-1)){dfs(tempx,tempy,step-3);}for(int j=0;j<3;j++)map[x+dir[i][j][0]][y+dir[i][j][1]]=0;}}if(i==2&&!x&&(y+1)<n){bool flag=true;for(int k=0;k<2;k++)for(int j=0;j<3;j++)if(map[x+dir[0][j][0]][y+dir[0][j][1]+k])flag=false;if(flag){if(6==step){count++;return ;}for(int k=0;k<2;k++)for(int j=0;j<3;j++) map[x+dir[0][j][0]][y+dir[0][j][1]+k]=-1;if(x*y<2*(n-1)-1){int tempx=x,tempy=y+2;if(tempy>=n){tempx++;tempy%=n;}dfs(tempx,tempy,step-6);for(int k=0;k<2;k++)for(int j=0;j<3;j++) map[x+dir[0][j][0]][y+dir[0][j][1]+k]=0;}}}if(i==3&&x<2&&y+2<n){bool flag=true;for(int k=0;k<2;k++)for(int j=0;j<3;j++)if(map[x+k+dir[1][j][0]][y+dir[1][j][1]])flag=false;if(flag){ int tempx=x,tempy=y+3;if(tempy>=n){tempx+=2;tempy%=n;}if(6==step){count++;return ;}if(tempx<3&&tempy*tempx<=2*(n-1)){for(int k=0;k<2;k++)for(int j=0;j<3;j++)map[x+k+dir[1][j][0]][y+dir[1][j][1]]=-1;dfs(tempx,tempy,step-6);for(int k=0;k<2;k++)for(int j=0;j<3;j++)map[x+k+dir[1][j][0]][y+dir[1][j][1]]=0;}}}if(i==4&&!x&&(y+2)<n){bool flag=true;for(int k=0;k<3;k++)for(int j=0;j<3;j++)if(map[k+x+dir[1][j][0]][y+dir[1][j][1]])flag=false;if(flag){if(9==step){count++;return ;}int tempx=x,tempy=y+3;if(tempy>=n){tempx++;tempy%=n;}if(tempx<3&&tempy*tempx<=2*(n-1)){for(int k=0;k<3;k++)for(int j=0;j<3;j++)map[x+k+dir[1][j][0]][y+dir[1][j][1]]=-1;dfs(tempx,tempy,step-9);for(int k=0;k<3;k++)for(int j=0;j<3;j++)map[x+k+dir[1][j][0]][y+dir[1][j][1]]=0;}}}}}}int main(){while(cin>>n){count=0;memset(map,0,sizeof(map));dfs(0,0,3*n);cout<<count<<endl;}return 0;}


AC递推代码(真TM短呀!):

#include<iostream>using namespace std;long long dp[51],n;int main(){dp[1]=1,dp[2]=2; dp[3]=7;for(int i=4;i<=50;i++)dp[i]=dp[i-1]+dp[i-2]+4*dp[i-3];while(cin>>n)cout<<dp[n]<<endl;return 0;}







0 0
原创粉丝点击