首页 > 代码库 > HDU2589 正方形划分 【DFS】

HDU2589 正方形划分 【DFS】

正方形划分

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 179    Accepted Submission(s): 87


Problem Description
一个边长为L的正方形可以分成 L*L个小正方形. 有N个石子放在 N个小正方形里,能否将它分成 N个 正方形,使得每个正方形里恰有一个石子且这N 个正方形恰好构成整个正方形 .
 

Input
输入数据首先包含一个整数T,表示测试实例的个数,然后是T组数据,每组第一行包含2个整数L,N,接下来有N行每行2个整数 r,c,表示第r行c列的小正方形里有一个石子 .1<L<=20;1<N<=L*L; 1<=r,c<=L.
 

Output
对于每个测试实例,如能将它分成 N个 正方形输出YES, 否则输出 NO
 

Sample Input
3 5 8 2 4 3 3 3 4 3 5 4 2 4 4 4 5 5 5 3 2 1 1 3 3 2 4 1 1 1 2 2 1 2 2
 

Sample Output
YES NO YES

 
很经典的搜索题。


#include <stdio.h>
#include <string.h>

bool vis[22][22], stone[22][22];
int L, N, cnt;

int cnt_stone(int x, int y, int len) {
	int cnt = 0, i, j;
	for (i = x; i < x + len; ++i)
		for (j = y; j < y + len; ++j)
			if (stone[i][j]) ++cnt;
	return cnt;
}

void paint(int x, int y, int len, bool col) {
	int i, j;
	for (i = x; i < x + len; ++i)
		for (j = y; j < y + len; ++j)
			vis[i][j] = col;
}

void getNext(int& x, int& y) {
	int i, j;
	for ( ; x < L; ++x, y = 0)
		for ( ; y < L; ++y)
			if (!vis[x][y]) return;
}

bool DFS(int x, int y) {
	int i, t;
	for (i = 1; i <= L; ++i) {
		if (x + i > L || y + i > L) break;
		t = cnt_stone(x, y, i);
		if (t == 0) continue;
		if (t == 1) {
			paint(x, y, i, true);
			cnt += i * i;
			if (cnt == L * L) return true;
			int xx = x, yy = y;
			getNext(x, y);
			if (x == L) {
				x = xx; y = yy;
				paint(x, y, i, false);
				cnt -= i * i;
				return false;
			}
			if (DFS(x, y)) return true;
		} else {
			paint(x, y, i, false);
			cnt -= i * i;
			return false;
		}
	}
	return false;
}

int main() {
	freopen("stdin.txt", "r", stdin);
	int T, i, x, y;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &L, &N);
		memset(vis, cnt = 0, sizeof(vis));
		memset(stone, 0, sizeof(stone));
		for (i = 0; i < N; ++i) {
			scanf("%d%d", &x, &y);
			stone[--x][--y] = true;
		}
		puts(DFS(0, 0) ? "YES" : "NO");
	}
	return 0;
}


HDU2589 正方形划分 【DFS】