cf515d

题意:给出一个矩阵迷宫,要求用1×2的积木填满空白区域,问解法是否唯一,如果无解或者多解均输出“Not unique"。

分析:广搜。看似二分图匹配但实际上不是。

我们认为每个点和上下左右四个点连接(只考虑空白的点)。先把度为0的点全部入队。

每次弹出一个点a,把那个唯一与它链接的点b与a配对。切断b的所有其他边,观察是否有点的度变为1,将这些点入队。

如此循环直到队列为空。如果仍有空白点未覆盖则必然not unique。因为剩下的点的度均大于1(如果有0的那就无解),所以一定有环存在。

环上只要把原来的配对依次串位一格则又是一种方法。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define D(x) 

const int MAX_N = (int)(2e3) + 10;

struct Point
{
    int x, y;
    Point()
    {}
    Point(int x, int y):x(x), y(y)
    {}
    Point operator + (const Point &a)
    {
        return Point(x + a.x, y + a.y);
    }
};

Point dir[8] = {Point(1, 0), Point(0, 1), Point(-1, 0), Point(0, -1),
};
int row_num, col_num;
char grid[MAX_N][MAX_N];

bool vis[MAX_N][MAX_N];
Point match[MAX_N][MAX_N];

bool out(Point a)
{
    return a.x < 0 || a.y < 0 || a.x >= row_num || a.y >= col_num;
}

bool minus_one(Point a)
{
    return a.x == -1 && a.y == -1;
}

void draw(Point a, char ch)
{
    grid[a.x][a.y] = ch;
}

void draw(Point a, Point b)
{
    if (a.x > b.x || a.y > b.y)
        swap(a, b);
    if (a.x == b.x)
    {
        draw(a, ‘<‘);
        draw(b, ‘>‘);
    }else
    {
        draw(a, ‘^‘);
        draw(b, ‘v‘);
    }
}

void output()
{
    for (int i = 0; i < row_num; i++)
        puts(grid[i]);
}

int get_degree(Point u)
{
    int ret = 0;
    for (int i = 0; i < 4; i++)
    {
        Point v = u + dir[i];
        if (out(v) || grid[v.x][v.y] != ‘.‘)
            continue;
        ret++;
    }
    return ret;
}

bool not_unique()
{
    queue<Point> q;
    for (int i = 0; i < row_num; i++)
    {
        for (int j = 0; j < col_num; j++)
        {
            if (get_degree(Point(i, j)) == 1)
            {
                q.push(Point(i, j));
            }
        }
    }

    while (!q.empty())
    {
        Point u = q.front();
        q.pop();
        if (grid[u.x][u.y] != ‘.‘)
            continue;
        D(printf("u %d %d\n", u.x, u.y));
        Point v;
        for (int i = 0; i < 4; i++)
        {
            v = u + dir[i];
            if (out(v) || grid[v.x][v.y] != ‘.‘)
                continue;
            draw(u, v);
            break;
        }
        u = v;
        for (int i = 0; i < 4; i++)
        {
            v = u + dir[i];
            if (out(v) || grid[v.x][v.y] != ‘.‘)
                continue;
            if (get_degree(v) == 1)
            {
                q.push(v);
            }
        }
    }

    for (int i = 0; i < row_num; i++)
    {
        for (int j = 0; j < col_num; j++)
        {
            if (grid[i][j] == ‘.‘)
            {
                return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d%d", &row_num, &col_num);
    for (int i = 0; i < row_num; i++)
    {
        scanf("%s", grid[i]);
    }

    if (not_unique())
    {
        puts("Not unique");
        return 0;
    }

    output();
    return 0;
}

时间: 2024-11-06 07:20:39

cf515d的相关文章