acmclub 1059 贴瓷砖

来源: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;
}







你可能感兴趣的:(Algorithm,动态规划,ACM,递推,acmclub)