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;
}
时间: 2024-12-11 07:37:53

HDU2589 正方形划分 【DFS】的相关文章

HDU2589 正方形划分【DFS】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2589 题目大意: 有一个边长为L的正方形有L*L个小正方形,将N个小石子放在N个小正方形中,给你N个小石子所放 位置,那么问题来了:能否将这个变成为L的正方形分割成N个正方形,使得每个正方形中都含有1个 小石子,并且这N个正方形正好构成整个正方形. 测试样例1说明: 边长为5的大正方形里有8个小石子,正好能将大正方形分解成8个小正方形,且每个正方形中有1个 小石子. 思路: 用DFS来做这道题.用

正方形划分【dfs】

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 对于

【蓝桥杯】第六届国赛C语言B组 2.完美正方形(dfs)

如果一些边长互不相同的正方形,可以恰好拼出一个更大的正方形,则称其为完美正方形. 历史上,人们花了很久才找到了若干完美正方形.比如:如下边长的22个正方形2 3 4 6 7 8 12 13 14 15 16 17 18 21 22 23 24 26 27 28 50 60如[图1.png]那样组合,就是一种解法.此时,紧贴上边沿的是:60 50紧贴下边沿的是:26 28 17 21 18 22阶完美正方形一共有8种.下面的组合是另一种:2 5 9 11 16 17 19 21 22 24 26

【HDOJ】2589 正方形划分

暴力DFS 1 /* 2589 */ 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 #define MAXN 21 7 8 bool map[MAXN][MAXN]; 9 bool visit[MAXN][MAXN]; 10 int l, n; 11 12 bool dfs(int cnt) { 13 int i, j, k; 14 int x, y, r; 15 int ex, ey

poj 1020 Anniversary Cake(切正方形蛋糕+搜索)

Anniversary Cake Nahid Khaleh decides to invite the kids of the "Shahr-e Ghashang" to her wedding anniversary. She wants to prepare a square-shaped chocolate cake with known size. She asks each invited person to determine the size of the piece o

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

杭电1518

HDOJ1518 Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11375    Accepted Submission(s): 3660 Problem Description Given a set of sticks of various lengths, is it possible to join them e

HDU 1518

题意:给你一些木棒,问这些木棒首尾相连能不能连成一个正方形. dfs+剪枝(卧槽一说剪枝瞬间高大上了 思路:首先看一看能不能被4整除,不能的话当然是NO:如果能的话,从头进行递归: 递归过程中,如果能够连成一条边,则继续往下递归,如果不能的话,立刻停止递归,消除标记. AC代码: #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namesp

树的一些基础东西

1.时间戳:  按照dfs的过程,将每个节点第一次被访问的顺序(v[x]被标记为1时),依次给这n个节点标记1-n的数字即该节点的时间戳. 代码: 1 void dfs(int x){ 2 v[x]=1;dfn[x]=++cnt; //dfn时间戳,cnt初始为0 3 for(int i=head[x];i;i=next[i]){ 4 int y=ver[i]; 5 if(v[y])continue; 6 dfs(y); 7 } 8 } 2.树的dfs序  第一次访问到某个节点时,记录其一次编号