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

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

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

每次弹出一个点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) + ; 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[] = {Point(, ), Point(, ), Point(-, ), Point(, -),
};
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 < || a.y < || a.x >= row_num || a.y >= col_num;
} bool minus_one(Point a)
{
return a.x == - && a.y == -;
} 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 = ; i < row_num; i++)
puts(grid[i]);
} int get_degree(Point u)
{
int ret = ;
for (int i = ; i < ; 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 = ; i < row_num; i++)
{
for (int j = ; j < col_num; j++)
{
if (get_degree(Point(i, j)) == )
{
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 = ; i < ; i++)
{
v = u + dir[i];
if (out(v) || grid[v.x][v.y] != '.')
continue;
draw(u, v);
break;
}
u = v;
for (int i = ; i < ; i++)
{
v = u + dir[i];
if (out(v) || grid[v.x][v.y] != '.')
continue;
if (get_degree(v) == )
{
q.push(v);
}
}
} for (int i = ; i < row_num; i++)
{
for (int j = ; j < col_num; j++)
{
if (grid[i][j] == '.')
{
return true;
}
}
}
return false;
} int main()
{
scanf("%d%d", &row_num, &col_num);
for (int i = ; i < row_num; i++)
{
scanf("%s", grid[i]);
} if (not_unique())
{
puts("Not unique");
return ;
} output();
return ;
}

cf515d的更多相关文章

随机推荐

  1. VS2012打包Winform教程 [转]

    VS2012打包部署Winform程序 打包前的准备工作: 里边会提到第一次使用的时候打开网页填数据什么的..最终要下载一个EXE文件..其实大可不必.. 直接百度InstallShield2012S ...

  2. 缓存 HttpContext.Current.Cache和HttpRuntime.Cache的区别

    先看MSDN上的解释: HttpContext.Current.Cache:为当前 HTTP 请求获取Cache对象. HttpRuntime.Cache:获取当前应用程序的Cache.  我们再用. ...

  3. iOS数据库学习(2)-基础SQL语句

    /* 1. 创建一个数据表 */ CREATE TABLE IF NOT EXISTS t_dog (name text, age integer); CREATE TABLE IF NOT EXIS ...

  4. box-sizing属性

    我们都知道,设置元素的padding或者margin属性时都会改变元素的width和height,传统的方法是将padding和margin的值考虑进去,运用数学的方法进行计算来加以调整,以便使布局不 ...

  5. UI第一节—— UILable

    1.首先说说怎么创建UI程序,打开xcode,选择Create  a new Xcode project.看如下截图 2,接下来就蹦出一个和写OC应用差不多的界面,不多解释了 3.我给工程取得名字就叫 ...

  6. 【C语言入门教程】4.5 指针变量的定义与引用

    指针变量是包含内存地址的变量.一般的变量直接包含一个特定的值,而指针变量包含的是某一特定数据类型的内存地址.普通变量直接引用其中的值,指针变量则间接引用所指向内存地址中的值.指针变量在使用前需要声明与 ...

  7. Bootstrap编码规范

    黄金定律 永远遵循同一套编码规范 -- 可以是这里列出的,也可以是你自己总结的.如果你发现本规范中有任何错误,敬请指正.通过 open an issue on GitHub为本规范添加或贡献内容. 不 ...

  8. Keepalived高可用集群介绍

    1.Keepalived服务介绍 Keepalived起初是专为LVS设计的,专门用来监控LVS集群系统中各个服务节点的状态,后来又加入了VRRP的功能,因此除了配合LVS服务外,也可以为其他服务(n ...

  9. Knockout.Js案例三单页面应用程序

    <ul data-bind="foreach: folders">      <li data-bind="text: $data">& ...

  10. 如何使用java自定义注解?demo

    1.Description.java package kzfy.bk.com; import java.lang.annotation.Documented; import java.lang.ann ...