链接:https://ac.nowcoder.com/acm/contest/301/B
来源:牛客网
小乐乐想要给自己搭建一个积木城堡。
积木城堡我们假设为n*m的平面矩形。
小乐乐现在手里有1*2,2*1两种地砖。
小乐乐想知道自己有多少种组合方案。
//本题给的范围较小,可暴力求解
首先因为每次我们能放的积木只有面积为2的,所以总的矩形面积若是为奇,则怎么也拼不出来。
要想拼完,我们首先想到的就是一个一个塞进去试,dfs暴力求解;
那么我们要注意的是终结时候的状态,因为有2*1和1*2两种,我们把最末状态分成1*1的单独状态来判断,只可以在原基础上或者右加1*1积木;
切分状态后的终止条件是所放积木的总面积等于给出n*m。
ps:这里的x,y因为本次面积下确定方式(横竖)不同,把二维数组折成一维,如果n=2,m=3,pos == 5时,则判断此次位置为(2,1);根据起始点的不同,如果定义dfs(1)开始,x = pos/m +1,y=pos%m,此时y会在所对应的位置就会在边上,其实下个位置应该是判断下一行的末尾,应当判断y == 0的情况和保证下面的xx<=n&&yy<=m;
if(y == 0)
{
x--;
y = m;
}
分割线:
#include<bits/stdc++.h>
using namespace std;
int vis[15][15];//二维图用二维数组表示
int dir[3][2] = {{0,1},{1,0}};//分割状态后我们能加的木块只有在原木块的上面或者右面;
int ans,n,m,s; //总方案,宽,长,总面积
void dfs(int pos){
if(pos == s){ //终止条件
ans++;
return;
}
int x = pos/m , y = pos % m; //x,y是当前面积下我们进行判断后放的下一积木的位置
//dfs(1)时y的判断
if(vis[x][y]){ //拆分状态后单独判断终止条件 ,且判断此次放的位置是否未被使用(上次放的积木被拆分的后位)
return dfs(pos+1);
}
for(int i = 0;i <= 1; ++i){//这就没啥说的了
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if(xx < n && yy < m && vis[xx][yy]==0){
vis[xx][yy] = 1;
vis[x][y] = 1;
dfs(pos+1);
vis[xx][yy] = 0;
vis[x][y] = 0;
}
}
return;
}
int main(){
cin>>n>>m;
s = n * m;
if(s&1){ //奇数面积无解
cout<<"0"<<endl;
return 0;
}
//memset(vis,0,sizeof(vis));
dfs(0);
cout<<ans<<endl;
return 0;
}