棋盘划分问题

在这里插入图片描述
思路:为了完整的用完(4^k - 1)/3 个L型骨牌,不妨采用四等分划分,对于没有特殊方格的区域构造一个L型骨牌,这样使得所有区域再放一下L型骨牌刚刚好把整个棋盘放满,然后再进行四等分递归划分,直到只有一个方格时才结束划分,应该算是一个经典的分治法吧。
代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 10;
int chess[maxn][maxn];
int cnt = 1;
void dfs(int sr,int sc,int len,int dx,int dy){
	if(len == 1)return; // 递归出口,即只有一个格子的时候 
	len /= 2; // 四等分划分即除二 
	cnt ++ ;//编号 
	if(dx < sr + len && dy < sc + len){ // 特殊方格在第一个区间 
		dfs(sr,sc,len,dx,dy); //无需放置L型骨牌,继续划分(len 已经改变) 
	}else{
		chess[sr + len -1][sc + len -1] = cnt;//特殊方格不在第一个区间,即需要放置L型骨牌 
		dfs(sr,sc,len,sr+len-1,sc+len-1);//放置完了后,当前区域的L型骨牌已经变成当前区域的特殊方格,继续划分(注意区域左上角和特殊方格的坐标变化) 
	}
	//下面的等价,不再赘述 
	if(dx < sr + len && dy >= sc + len){
		dfs(sr,sc + len,len,dx,dy);
	}else{
		chess[sr + len - 1][sc + len] = cnt;
		dfs(sr,sc + len,len,sr + len - 1,sc + len);
	}
	
	if(dx >= sr + len && dy < sc + len){
		dfs(sr + len,sc,len,dx,dy);
	}else{
		chess[sr + len][sc + len - 1] = cnt;
		dfs(sr + len,sc,len,sr + len,sc + len -1);
	}
	
	if(dx >= sr + len && dy >= sc + len){
		dfs(sr + len , sc + len ,len,dx,dy);
	}else{
		chess[sr + len][sc + len] = cnt;
		dfs(sr + len , sc + len , len ,sr + len, sc + len);
	}
}
int main(){
	srand(time(0));
	int k;cin>>k;
	int len = 1 << k;//2 ^ k
	int r = rand()%len + 1;//2 ^ k * 2 ^ k 方格种随机省生成一个特殊方格 
	int c = rand()%len + 1;
	chess[r][c] = 1;//标号 
	dfs(1,1,len,r,c);//递归划分  
	for(int i = 1; i <= len ; i++){
		for(int j = 1 ; j <= len ; j++){
			cout<<chess[i][j]<<" ";
		}
		cout<<endl;
	}
} 

修正版:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 10;
int chess[maxn][maxn];
int len = 0,t = 1;
void display();
void dfs(int sr,int sc,int len,int dx,int dy){
	if(len == 1)return; // 递归出口,即只有一个格子的时候 
	len /= 2; // 四等分划分即除二 
	int cnt = ++t ;//编号 
	if(dx < sr + len && dy < sc + len){ // 特殊方格在第一个区间 
		dfs(sr,sc,len,dx,dy); //无需放置L型骨牌,继续划分(len 已经改变) 
		display();
	}else{
		chess[sr + len -1][sc + len -1] = cnt;//特殊方格不在第一个区间,即需要放置L型骨牌 
		dfs(sr,sc,len,sr+len-1,sc+len-1);//放置完了后,当前区域的L型骨牌已经变成当前区域的特殊方格,继续划分(注意区域左上角和特殊方格的坐标变化) 
		display();
	}
	//下面的等价,不再赘述 
	if(dx < sr + len && dy >= sc + len){
		dfs(sr,sc + len,len,dx,dy);
		display();
	}else{
		chess[sr + len - 1][sc + len] = cnt;
		dfs(sr,sc + len,len,sr + len - 1,sc + len);
		display();
	}
	
	if(dx >= sr + len && dy < sc + len){
		dfs(sr + len,sc,len,dx,dy);
		display();
	}else{
		chess[sr + len][sc + len - 1] = cnt;
		dfs(sr + len,sc,len,sr + len,sc + len -1);
		display();
	}
	
	if(dx >= sr + len && dy >= sc + len){
		dfs(sr + len , sc + len ,len,dx,dy);
		display();
	}else{
		chess[sr + len][sc + len] = cnt;
		dfs(sr + len , sc + len , len ,sr + len, sc + len);
		display();
	}
}
int main(){
	srand(time(0));
	int k;cin>>k;
	len = 1 << k;//2 ^ k
	int r = rand()%len + 1;//2 ^ k * 2 ^ k 方格种随机省生成一个特殊方格 
	int c = rand()%len + 1;
	chess[r][c] = 1;//标号 
	display();
	dfs(1,1,len,r,c);//递归划分  
	display();
} 

void display(){
	for(int i = 1; i <= len ; i++){
		for(int j = 1 ; j <= len ; j++){
			cout<<chess[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<endl;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值