第九届蓝桥杯决赛(C++B组):搭积木

搭积木

题目描述:

小明对搭积木非常感兴趣。他的积木都是同样大小的正立方体。在搭积木时,小明选取 m 块积木作为地基,将他们在桌子上一字排开,中间不留空隙,并称其为第0层。随后,小明可以在上面摆放第1层,第2层,……,最多摆放至第n层。摆放积木必须遵循三条规则:

规则1:每块积木必须紧挨着放置在某一块积木的正上方,与其下一层的积木对齐;规则2:同一层中的积木必须连续摆放,中间不能留有空隙;规则3:小明不喜欢的位置不能放置积木。

其中,小明不喜欢的位置都被标在了图纸上。图纸共有n行,从下至上的每一行分别对应积木的第1层至第n层。每一行都有m个字符,字符可能是‘.’或‘X’,其中‘X’表示这个位置是小明不喜欢的。现在,小明想要知道,共有多少种放置积木的方案。他找到了参加ACM的你来帮他计算这个答案。由于这个答案可能很大,你只需要回答这个答案对1000000007(十亿零七)取模后的结果。注意:地基上什么都不放,也算作是方案之一种。

输入

输入数据的第一行有两个正整数n和m,表示图纸的大小。随后n行,每行有m个字符,用来描述图纸 。每个字符只可能是‘.’或‘X’。

输出

输出一个整数,表示答案对1000000007取模后的结果。

样例输入1

2 3
..X
.X.

样例输出1

4

样例输入2

3 3
..X
.X.
...

样例输出 2

16
 

#include<iostream>
using namespace std;
#include<map>
map<string,int> mp;//定义map集合,查重
int m,n;
char arr[101][101];
int sum=0;
void disp(){//为了方便理解,将所有符合条件的积木都输出
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cout<<arr[i][j]<<ends;
		}
		cout<<endl;
	}
}
bool fun(){//查重
	string s;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			s+=arr[i][j];
		}
	}
	if(mp[s])
		return false;
	mp[s]++;
	return true;
}
bool fun2(int x,int y){//判断该位置是否可以放置积木
	if(arr[x][y]!='X'){//如果该位置不为'X'
		if(x==m-1){//如果在最底层
			if(y==0||arr[x][y-1]=='O')//判断处在第一列或者旁边列放置了积木,因为题目要求积木要连续放置
				return true; 
		}else{//不在第一层,就要多满足一个条件,即 该积木所在的下一行有积木
			if((y==0||arr[x][y-1]=='O')&&arr[x+1][y]=='O')
				return true;
		}//如果隔壁没有摆放积木,那么只要遍历到隔壁积木位置的前面列也没有放置积木就符合条件
		if(arr[x][y-1]!='O'&&((x==m-1)||(arr[x+1][y]=='O'))){
			for(int i=0;i<y-1;i++){
				if(arr[x][i]=='O'){
					return false;
				}
			}
			return true;
		}
	}
	return false;
}
void dfs(int x,int y){
	if(x<0){//递归出口,即当到了最顶层的上层
		if(fun()){//如果满足没有重复
			sum++;
			cout<<'('<<sum<<')'<<endl;
			disp();
			return ;
		}
	}else{
		if(fun2(x,y)){//如果可以放置
				arr[x][y]='O';//放置积木
				if(y==n-1){//如果在最后一列
					dfs(x-1,0);//就堆下一层
				}else{
					dfs(x,y+1);//不然就堆旁边
				}
				arr[x][y]='.';//不放积木
				if(y==n-1){
					dfs(x-1,0);
				}else{
					dfs(x,y+1);
				}
		}else{
				if(y==n-1){
						dfs(x-1,0);
					}else{
						dfs(x,y+1);
				}
		}
	}
	
}

int main(){
	cin>>m>>n;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			cin>>arr[i][j];
		}
	}	
	for(int i=0;i<n;i++){//从最底层的每一个位置开始堆积木
		if(arr[m-1][i]=='.'){
			dfs(m-1,i);
		}
	}
	cout<<sum%1000000007<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40871196/article/details/89444741
今日推荐