poj3133 Manhattan Wiring
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 2016 | Accepted: 1162 |
Description
There is a rectangular area containing n × m cells. Two cells are marked with “2”, and another two with “3”. Some cells are occupied by obstacles. You should connect the two “2”s and also the two “3”s with non-intersecting lines. Lines can run only vertically or horizontally connecting centers of cells without obstacles.
Lines cannot run on a cell with an obstacle. Only one line can run on a cell at most once. Hence, a line cannot intersect with the other line, nor with itself. Under these constraints, the total length of the two lines should be minimized. The length of a line is defined as the number of cell borders it passes. In particular, a line connecting cells sharing their border has length 1.
Fig. 1(a) shows an example setting. Fig. 1(b) shows two lines satisfying the constraints above with minimum total length 18.
![](http://poj.org/images/3133_1.png)
Figure 1: An example of setting and its solution
Input
The input consists of multiple datasets, each in the following format.
n m row1 … rown
n is the number of rows which satisfies 2 ≤ n ≤ 9. m is the number of columns which satisfies 2 ≤ m ≤ 9. Each rowi is a sequence of m digits separated by a space. The digits mean the following.
0:
Empty
1:
Occupied by an obstacle
2:
Marked with “2”
3:
Marked with “3”
The end of the input is indicated with a line containing two zeros separated by a space.
Output
For each dataset, one line containing the minimum total length of the two lines should be output. If there is no pair of lines satisfying the requirement, answer “0
” instead. No other characters should be contained in the output.
Sample Input
5 5 0 0 0 0 0 0 0 0 3 0 2 0 2 0 0 1 0 1 1 1 0 0 0 0 3 2 3 2 2 0 0 3 3 6 5 2 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 2 3 0 5 9 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 9 9 3 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 3 9 9 0 0 0 1 0 0 0 0 0 0 2 0 1 0 0 0 0 3 0 0 0 1 0 0 0 0 2 0 0 0 1 0 0 0 0 3 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 9 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 0 0
Sample Output
18 2 17 12 0 52 43题目大意:找两条不相交的路径将矩阵中的2连起来并将3连起来,求最小路径长度和-2.分析:挺神的一道题. 用插头表示左括号右括号肯定是不够的.那表示什么呢?和bzoj2331类似,他要求什么就表示什么嘛. 令状态0表示不存在插头,状态2表示这个插头是连接2的插头,状态3表示这个插头是连接3的插头. 这样会有一个问题:如何确保一条路径2个2,2个3都经过呢? 可以在转移的时候强行规定:如果不存在插头,那么空地只能建一对状态相同的插头,标记2或者3的地方只能建一个状态与之对应的插头. 这一对和一个有啥区别? 一对表示这个点会经过两次2或3,一个表示这个点已经经过2或3了,只需要再经过一次即可. 转移要分很多类,参看:传送门. 总得来说就是讨论. 看当前所在格子是哪一类格子,由此可以得出转移到的格子有什么限制,再来讨论看看是否符合这些限制来进行转移.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int maxn = 60010,inf = 0x7ffffff; int n,m,a[20][20],pow[110],ans = inf,now,pre;struct node {int head[maxn],nextt[maxn],sum[maxn],sta[maxn],tot;void clear(){memset(head,-1,sizeof(head));tot = 0;memset(sum,127 / 3,sizeof(sum));}void push(int x,int v){int hashh = x % maxn;for (int i = head[hashh]; i >= 0; i = nextt[i]){if (sta[i] == x){sum[i] = min(sum[i],v);return;}}sum[tot] = v;sta[tot] = x;nextt[tot] = head[hashh];head[hashh] = tot++;} }f[2];int turnleft(int x,int pos) {return x << pow[pos]; }int get(int x,int pos) {return (x >> pow[pos]) & 3; }int del(int x,int i,int j) {return x & (~(3 << pow[i])) & (~(3 << pow[j])); }void solve2(int x,int y,int k) {int p = get(f[pre].sta[k],y - 1);int q = get(f[pre].sta[k],y);int staa = del(f[pre].sta[k],y - 1,y);int v = f[pre].sum[k];if (staa > (1 << pow[m + 1]))return;if (a[x][y] == 1){if (p + q == 0){f[now].push(staa,v);return;}}else if (!p && !q){if (a[x][y] == 0){f[now].push(staa,v);if (a[x + 1][y] + a[x][y + 1] == 5 || a[x + 1][y] == 1 || a[x][y + 1] == 1)return;if (a[x + 1][y] == 2 || a[x][y + 1] == 2)f[now].push(staa | turnleft(2,y - 1) | turnleft(2,y),v + 1);else if (a[x + 1][y] == 3 || a[x][y + 1] == 3)f[now].push(staa | turnleft(3,y - 1) | turnleft(3,y),v + 1);else{f[now].push(staa | turnleft(2,y - 1) | turnleft(2,y),v + 1);f[now].push(staa | turnleft(3,y - 1) | turnleft(3,y),v + 1);}}else{if (a[x + 1][y] != 5 - a[x][y] && a[x + 1][y] != 1)f[now].push(staa | turnleft(a[x][y],y - 1),v + 1);if (a[x][y + 1] != 5 - a[x][y] && a[x][y + 1] != 1)f[now].push(staa | turnleft(a[x][y],y),v + 1);}}else if (p && q){if (p + q == 5 || a[x][y] != 0)return;f[now].push(staa,v + 1);}else if (p && !q){if (a[x][y] == 0){if (a[x][y + 1] == 0 || a[x][y + 1] == p)f[now].push(staa | turnleft(p,y),v + 1);if (a[x + 1][y] == 0 || a[x + 1][y] == p)f[now].push(staa | turnleft(p,y - 1),v + 1);}else if (a[x][y] == p)f[now].push(staa,v + 1);}else if (!p && q){if (a[x][y] == 0){if (a[x][y + 1] == 0 || a[x][y + 1] == q)f[now].push(staa | turnleft(q,y),v + 1);if (a[x + 1][y] == 0 || a[x + 1][y] == q)f[now].push(staa | turnleft(q,y - 1),v + 1);}else if (a[x][y] == q)f[now].push(staa,v + 1);} }void solve() {now = 0,pre = 1;f[0].clear();f[0].push(0,0);for (int i = 1; i <= n; i++){pre = now;now ^= 1;f[now].clear();for (int k = 0; k < f[pre].tot; k++)f[now].push(turnleft(f[pre].sta[k],1),f[pre].sum[k]);for (int j = 1; j <= m; j++){pre = now;now ^= 1;f[now].clear();for (int k = 0; k < f[pre].tot; k++)solve2(i,j,k);}}for (int i = 0; i < f[now].tot; i++)if (f[now].sta[i] == 0)ans = min(ans,f[now].sum[i]); }int main() {for (int i = 1; i <= 100; i++)pow[i] = i * 2;while (scanf("%d%d",&n,&m) == 2 && (n + m)){ans = inf;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)scanf("%d",&a[i][j]);solve();if (ans == inf)puts("0");elseprintf("%d\n",ans - 2);}return 0; }
转载于:https://www.cnblogs.com/zbtrs/p/8460609.html
poj3133 Manhattan Wiring相关推荐
- [POJ3133]Manhattan Wiring 插头dp
[POJ3133]Manhattan Wiring 插头dp 原题POJ3133 题意:N*M有障碍矩阵,0可通过,1为障碍,两个2,两个3,求连接两个2和连接两个3的两条不相交路径长度和的最小值(1 ...
- [Poj3133]Manhattan Wiring (插头DP)
Description 题目大意:给你个N x M(1≤N, M≤9)的矩阵,0表示空地,1表示墙壁,2和3表示两对关键点.现在要求在两对关键点之间建立两条路径,其中两条路径不可相交或者自交(就是重复 ...
- POJ 3133 Manhattan Wiring (插头DP)
Manhattan Wiring Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 1110 Accepted: 634 D ...
- POJ 3133 Manhattan Wiring(限制匹配的插头DP)
Manhattan Wiring Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 1921 Accepted: 1130 ...
- [LA3620]Manhattan Wiring
[LA3620]Manhattan Wiring 试题描述 输入 输出 输入示例 5 5 0 0 0 0 0 0 0 0 3 0 2 0 2 0 0 1 0 1 1 1 0 0 0 0 3 2 3 2 ...
- 【POJ3133】Manhattan Wiring 插头DP
原题走这里 看起来就很难的一道题 本题存在一个小陷阱,它看起来像是单回路模型(毕竟是求路径),然而它其实是多回路模型,或者说可以用多回路模型做. 这道题求的是最短距离,那么这就意味着如果出现了多出来的 ...
- POJ 3133 Manhattan Wiring(插头DP)
题目链接:http://poj.org/problem?id=3133 题意:n*m的格子中有两个2和两个3,其余是空白或障碍.找出两条路径分别连接2和3,不经过障碍且不相交.使得两条路径长度和最短? ...
- POJ 3133 Manhattan Wiring
辣鸡题目,毁我青春,费我时间,害我性命. 白书上的题目,轮廓线状压DP真是无爱了. 思考半小时,代码两小时TAT,我又回忆起了NOIP上写的那个脑残状压DP了,坑爹的优化...... 不过好歹1A了是 ...
- POJ 3133 Manhattan Wiring 笔记
n*m矩阵,1 代表障碍物,如图,要求连线 2 与连线 3 不能有交点.求两个连线和的最小长度.
最新文章
- 底盘智能化的关键技术探讨
- Python 列表(List) 取区间元素 [:] 用法
- JPA学习---第五节:日期和枚举等字段类型的JPA映射
- felzenszwalb算法_学习图像场景解析的理论和应用(二)场景解析的经典算法分析之SLIC...
- protobuf扫盲
- 利用FPGA实现外设通信接口之:利用FPGA实现USB 2.0通信接口
- javaweb简单的登录增删改查系统_利用python操作小程序云数据库实现简单的增删改查!
- [转载] python radians函数_Python numpy.radians() 使用实例
- 经典视觉SLAM框架
- mysql多条件顺序_mysql顺序由多个条件
- 计算机三角符号,word标尺倒三角 word倒三角符号
- 幕布笔记按字母顺序导出(Python+Opml)
- office起动缓慢_如何解决Microsoft Outlook启动缓慢的问题
- 《纽约客》:还原真实的扎克伯格
- net start命令发生系统错误5和错误1058的解决方法
- 平安京s9服务器维护,决战平安京S9赛季段位怎么继承_决战平安京S9赛季段位继承详情_素材吧...
- VGA带音频转HDMI转换芯片|VGA转HDMI 转换器方案|VGA转HDMI1.4转换器芯片介绍
- 西安三本计算机专业可报院校,西安三本大学前十名, 西北大学现代学院仅第四...
- 职业高一计算机试题,信息技术教师考试题库
- python pie函数_matplotlib 知识点11:绘制饼图(pie 函数精讲)