题意:给出一个矩阵迷宫,要求用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. verilog阻塞与非阻塞的初步理解(三)

    下面这段源码是因为习惯不好,出现不正确波形的例子. module pwm_division(reset,clkin,clkout); input reset,clkin; output clkout; ...

  2. Centos安装Kafka集群

    kafka是LinkedIn开发并开源的一个分布式MQ系统,现在是Apache的一个孵化项目.在它的主页描述kafka为一个高吞吐量的分布式(能 将消息分散到不同的节点上)MQ.在这片博文中,作者简单 ...

  3. 【转】常用的shell脚本

    from:http://blog.sina.com.cn/s/blog_4152a9f501013r6c.html 常用的shell脚本 (2012-10-10 22:09:07) 转载▼ 标签: 杂 ...

  4. CF469D Two Set (并查集)

    Codeforces Round #268 (Div. 2)D Codeforces Round #268 (Div. 1)B CF468B D. Two Sets time limit per te ...

  5. thinkphp 完整配置config.php

    ThinkPHP的系统配置都采用数组形式,配置文件地址:Bin/Conf/config.php CHECK_FILE_CASE -- windows环境下面的严格检查大小写.     /* 项目设定 ...

  6. oracle 中的trunc()函数及加一个月,一天,一小时,一分钟,一秒钟方法

    返回处理后的数据,不同于round()(对数值进行四舍五入处理),该函数不对指定小数前或后的数值部分进行舍入处理. 语法:trunc(number[,decimals]) 其中,number为待做处理 ...

  7. [设计模式] Javascript 之 观察者模式

    观察者模式:定议 定义对象间的一种一对多的关系,当一个对象状态改变时 (一般称为被观察者),依赖于该对象的对象被通知,并更新; 观察者模式:说明 1. 观察者模式是行为模式,也被称为:发布-订阅模式. ...

  8. EF-Linq将查询结果转换为List<string>

    List<int> id_list = new List<int>() { 1 };//测试数据...List<string> guid_list = (from ...

  9. 未能从程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中加载类型“System.ServiceModel.Activation.HttpModule”。

    ********************************* 思路壹(也是网络上铺天盖地的通俗解决方案) 原因: 这是因为先安装了 .NET Framework , 随后启用了 .NET Fra ...

  10. 第31天 mvp

    interactor调用接口 Activity包含Presenter,这样界面上的操作就会通知到Presenter. Presenter调用view接口, Activity实现view接口,这样Pre ...