正方形划分
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
很经典的搜索题。
2015.4.6更新
#include <stdio.h>
#include <string.h>
const int maxn = 22;
bool grid[maxn][maxn];
bool vis[maxn][maxn];
int L, N;
int countStone(int x, int y, int len) {
int cnt = 0;
for (int i = 0; i < len; ++i)
for (int j = 0; j < len; ++j)
if (grid[x+i][y+j]) ++cnt;
return cnt;
}
void paintVis(int x, int y, int len, bool sign) {
for (int i = 0; i < len; ++i)
for (int j = 0; j < len; ++j)
vis[x+i][y+j] = sign;
}
void getNext(int *x, int *y) {
for (int i = 1; i <= L; ++i)
for (int j = 1; j <= L; ++j)
if (vis[i][j] == false) {
*x = i; *y = j;
return;
}
}
bool findLayout(int x, int y, int n) {
int len = 1, stone, u, v;
for ( ; x + len <= L + 1 && y + len <= L + 1; ++len) {
if ((stone = countStone(x, y, len)) == 0)
continue;
else if (stone > 1) return false;
paintVis(x, y, len, true);
if (!(n -= len * len)) return true;
if (getNext(&u, &v), findLayout(u, v, n))
return true;
else {
paintVis(x, y, len, false);
n += len * len;
}
}
return false;
}
int main() {
int T, x, y;
scanf("%d", &T);
while (T--) {
memset(grid, 0, sizeof(grid));
memset(vis, 0, sizeof(vis));
scanf("%d%d", &L, &N);
for (int i = 0; i < N; ++i) {
scanf("%d%d", &x, &y);
grid[x][y] = true;
}
puts(findLayout(1, 1, L * L) ? "YES" : "NO");
}
return 0;
}
#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;
}