UVa 11694 Goigen Naname 谜题 DFS 剪枝 并查集

题目描述:

输入一个网格,某些网格的点上标有数字,表示这个点的度数,你需要在格子中填入正斜杠或者反斜杠,要求使度数与给定的度数相等,输出任意一组解即可(原题目的输入样例少输入了样例组数),下图是一个例子:
在这里插入图片描述

题解:

本题可以使用并查集来判环,注意使用并查集的话不能使用路径压缩,不然回溯的时候会丢失信息。
我们可以按照位置进行搜索,依次考虑当前位置填入正斜杠和反斜杠,然后判断当前的度数是否满足条件即可。
除此之外我们可以使用一些剪枝来减少搜索状态,我们需要记录当前每个点上的度数和改点最多还能增加多少度数,搜索之前需要先判断,受到影响的四个点是否能够达到输入的要求,不能的话我们直接剪枝即可。

代码:

#include <bits/stdc++.h>

const int MAXN = 7;
const int NUM_DIRECTION = 4;

using namespace std;

int T, n;
char ans[MAXN + 1][MAXN + 1], grid[MAXN + 2][MAXN + 2]; // 注意字符串末尾结束符也要占用空间
int limit[MAXN + 1][MAXN + 1], num[MAXN + 1][MAXN + 1];
int h[(MAXN + 1) * (MAXN + 1)];
int dx[] = {
    
    0, 0, 1, 1};
int dy[] = {
    
    0, 1, 1, 0};

int find(int x) {
    
     return h[x] == x ? x : find(h[x]); }

bool check(int x, int y)
{
    
    
    for (int i = 0; i < NUM_DIRECTION; i++) {
    
    
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (grid[nx][ny] == '.') {
    
     continue; }
        if (i == 0 && num[nx][ny] != grid[nx][ny] - '0') {
    
     return false; }
        if (num[nx][ny] <= grid[nx][ny] - '0' &&
            num[nx][ny] + limit[nx][ny] >= grid[nx][ny] - '0') {
    
     continue; }
        return false;
    }
    return true;
}

bool dfs(int x, int y)
{
    
    
    if (y == n) {
    
    
        x++;
        y = 0;
    }
    if (x == n) {
    
     return true; }
    for (int i = 0; i < NUM_DIRECTION; i++) {
    
     limit[x + dx[i]][y + dy[i]]--; }
    num[x][y]++, num[x + 1][y + 1]++;
    if (check(x, y)) {
    
    
        int fa = find(x * (n + 1) + y);
        int fb = find((x + 1) * (n + 1) + y + 1);
        if (fa != fb) {
    
     // 没有形成环
            h[fa] = fb;
            ans[x][y] = '\\';
            if (dfs(x, y + 1)) {
    
     return true; }
            ans[x][y] = 0;
            h[fa] = fa;
        }
    }
    num[x + 1][y + 1]--, num[x][y]--;

    num[x][y + 1]++, num[x + 1][y]++;
    if (check(x, y)) {
    
    
        int fa = find(x * (n + 1) + y + 1);
        int fb = find((x + 1) * (n + 1) + y);
        if (fa != fb) {
    
    
            h[fa] = fb;
            ans[x][y] = '/';
            if (dfs(x, y + 1)) {
    
     return true; }
            ans[x][y] = 0;
            h[fa] = fa;
        }
    }
    num[x + 1][y]--, num[x][y + 1]--;
    for (int i = 0; i < NUM_DIRECTION; i++) {
    
     limit[x + dx[i]][y + dy[i]]++; }
    return false;
}

int main()
{
    
    
    cin >> T;
    while (T--) {
    
    
        cin >> n;
        memset(ans, 0, sizeof(ans));
        memset(num, 0, sizeof(num));
        for (int i = 0; i < (n + 1) * (n + 1); i++) {
    
     h[i] = i;}
        for (int i = 0; i < n + 1; i++) {
    
     cin >> grid[i]; }
        for (int i = 0; i < n + 1; i++) {
    
    
            for (int j = 0; j < n + 1; j++) {
    
    
                if ((i == 0 && j == 0) || (i == 0 && j == n) ||
                    (i == n && j == 0) || (i == n && j == n)) {
    
    
                    limit[i][j] = 1;
                } else if (i == 0 || j == 0 || i == n || j == n) {
    
    
                    limit[i][j] = 2;
                } else {
    
    
                    limit[i][j] = 4;
                }
            }
        }
        dfs(0, 0);
        for (int i = 0; i < n; i++) {
    
     cout << ans[i] << endl; }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45523675/article/details/129431638
今日推荐