1. 程式人生 > 其它 >洛谷 P1228 地毯填補問題(分治)

洛谷 P1228 地毯填補問題(分治)

傳送門


解題思路

乍一看像是構造題。
我們從簡單開始想。
當有一個2*2的方格,很顯然可以直接鋪上。
於是我們發現,當一個矩形的1/4已經鋪好後,剩下的也可以鋪。
就像下圖一樣:(圖片來源:洛谷網校)

突破點:在已經鋪好的1/4的矩形正對著的位置鋪一個。
就像這樣:

所以可以分治處理,判斷已經填好的矩形在哪個位置。

AC程式碼

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
int x,y,k;
void divide(int lx,int ly,int rx,int ry,int x,int y){
	if(lx==rx&&ly==ry){
		return;
	}
	int midx=(lx+rx)/2,midy=(ry+ly)/2;
	if(x>=lx&&x<=midx&&y>=ly&&y<=midy){
		cout<<midx+1<<" "<<midy+1<<" "<<1<<endl;
		divide(lx,ly,midx,midy,x,y);
		divide(lx,midy+1,midx,ry,midx,midy+1);
		divide(midx+1,ly,rx,midy,midx+1,midy);
		divide(midx+1,midy+1,rx,ry,midx+1,midy+1);
		return;
	}
	if(x>midx&&x<=rx&&y>=ly&&y<=midy){
		cout<<midx<<" "<<midy+1<<" "<<3<<endl;
		divide(lx,ly,midx,midy,midx,midy);
		divide(lx,midy+1,midx,ry,midx,midy+1);
		divide(midx+1,ly,rx,midy,x,y);
		divide(midx+1,midy+1,rx,ry,midx+1,midy+1);
		return;
	}
	if(x>=lx&&x<=midx&&y>midy&&y<=ry){
		cout<<midx+1<<" "<<midy<<" "<<2<<endl;
		divide(lx,ly,midx,midy,midx,midy);
		divide(lx,midy+1,midx,ry,x,y);
		divide(midx+1,ly,rx,midy,midx+1,midy);
		divide(midx+1,midy+1,rx,ry,midx+1,midy+1);
		return;
	}
	if(x>midx&&x<=rx&&y>midy&&y<=ry){
		cout<<midx<<" "<<midy<<" "<<4<<endl;
		divide(lx,ly,midx,midy,midx,midy);
		divide(lx,midy+1,midx,ry,midx,midy+1);
		divide(midx+1,ly,rx,midy,midx+1,midy);
		divide(midx+1,midy+1,rx,ry,x,y);
		return;
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>k>>x>>y;
	divide(1,1,1<<k,1<<k,x,y);
    return 0;
}