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

 
很經典的搜索題。

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章