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.

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 = ,inf = 0x7ffffff;
int n,m,a[][],pow[],ans = inf,now,pre; struct node
{
int head[maxn],nextt[maxn],sum[maxn],sta[maxn],tot;
void clear()
{
memset(head,-,sizeof(head));
tot = ;
memset(sum, / ,sizeof(sum));
}
void push(int x,int v)
{
int hashh = x % maxn;
for (int i = head[hashh]; i >= ; 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[]; int turnleft(int x,int pos)
{
return x << pow[pos];
} int get(int x,int pos)
{
return (x >> pow[pos]) & ;
} int del(int x,int i,int j)
{
return x & (~( << pow[i])) & (~( << pow[j]));
} void solve2(int x,int y,int k)
{
int p = get(f[pre].sta[k],y - );
int q = get(f[pre].sta[k],y);
int staa = del(f[pre].sta[k],y - ,y);
int v = f[pre].sum[k];
if (staa > ( << pow[m + ]))
return;
if (a[x][y] == )
{
if (p + q == )
{
f[now].push(staa,v);
return;
}
}
else if (!p && !q)
{
if (a[x][y] == )
{
f[now].push(staa,v);
if (a[x + ][y] + a[x][y + ] == || a[x + ][y] == || a[x][y + ] == )
return;
if (a[x + ][y] == || a[x][y + ] == )
f[now].push(staa | turnleft(,y - ) | turnleft(,y),v + );
else if (a[x + ][y] == || a[x][y + ] == )
f[now].push(staa | turnleft(,y - ) | turnleft(,y),v + );
else
{
f[now].push(staa | turnleft(,y - ) | turnleft(,y),v + );
f[now].push(staa | turnleft(,y - ) | turnleft(,y),v + );
}
}
else
{
if (a[x + ][y] != - a[x][y] && a[x + ][y] != )
f[now].push(staa | turnleft(a[x][y],y - ),v + );
if (a[x][y + ] != - a[x][y] && a[x][y + ] != )
f[now].push(staa | turnleft(a[x][y],y),v + );
}
}
else if (p && q)
{
if (p + q == || a[x][y] != )
return;
f[now].push(staa,v + );
}
else if (p && !q)
{
if (a[x][y] == )
{
if (a[x][y + ] == || a[x][y + ] == p)
f[now].push(staa | turnleft(p,y),v + );
if (a[x + ][y] == || a[x + ][y] == p)
f[now].push(staa | turnleft(p,y - ),v + );
}
else if (a[x][y] == p)
f[now].push(staa,v + );
}
else if (!p && q)
{
if (a[x][y] == )
{
if (a[x][y + ] == || a[x][y + ] == q)
f[now].push(staa | turnleft(q,y),v + );
if (a[x + ][y] == || a[x + ][y] == q)
f[now].push(staa | turnleft(q,y - ),v + );
}
else if (a[x][y] == q)
f[now].push(staa,v + );
}
} void solve()
{
now = ,pre = ;
f[].clear();
f[].push(,);
for (int i = ; i <= n; i++)
{
pre = now;
now ^= ;
f[now].clear();
for (int k = ; k < f[pre].tot; k++)
f[now].push(turnleft(f[pre].sta[k],),f[pre].sum[k]);
for (int j = ; j <= m; j++)
{
pre = now;
now ^= ;
f[now].clear();
for (int k = ; k < f[pre].tot; k++)
solve2(i,j,k);
}
}
for (int i = ; i < f[now].tot; i++)
if (f[now].sta[i] == )
ans = min(ans,f[now].sum[i]);
} int main()
{
for (int i = ; i <= ; i++)
pow[i] = i * ;
while (scanf("%d%d",&n,&m) == && (n + m))
{
ans = inf;
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
scanf("%d",&a[i][j]);
solve();
if (ans == inf)
puts("");
else
printf("%d\n",ans - );
} return ;
}
poj3133 Manhattan Wiring的更多相关文章
- [Poj3133]Manhattan Wiring (插头DP)
Description 题目大意:给你个N x M(1≤N, M≤9)的矩阵,0表示空地,1表示墙壁,2和3表示两对关键点.现在要求在两对关键点之间建立两条路径,其中两条路径不可相交或者自交(就是重复 ...
- [LA3620]Manhattan Wiring
[LA3620]Manhattan Wiring 试题描述 输入 输出 输入示例 输出示例 数据规模及约定 见“输入” 题解 我们把“连线”的过程改为“铺地砖”的过程,总共有 11 种地砖,每种地砖上 ...
- 【poj3133】 Manhattan Wiring
http://poj.org/problem?id=3133 (题目链接) 题意 $n*m$的网格里有空格和障碍,还有两个$2$和两个$3$.要求把这两个$2$和两个$3$各用一条折线连起来.障碍里不 ...
- 【POJ】3133 Manhattan Wiring
http://poj.org/problem?id=3133 题意:n×m的网格,有2个2,2个3,他们不会重合.还有障碍1.现在求2到2的路径和3到3的路径互不相交的最短长度-2.(2<=n, ...
- poj 3133 Manhattan Wiring
http://poj.org/problem?id=3133 考虑插头 dp 用四进制表示一个插头的状态,0 表示没有插头,2 表示这个插头是连接两个 2 的,3 同理 然后就是大力分类讨论了 这题还 ...
- uva1214 Manhattan Wiring 插头DP
There is a rectangular area containing n × m cells. Two cells are marked with “2”, and another two w ...
- POJ 3133 Manhattan Wiring (插头DP,轮廓线,经典)
题意:给一个n*m的矩阵,每个格子中有1个数,可能是0或2或3,出现2的格子数为2个,出现3的格子数为2个,要求将两个2相连,两个3相连,求不交叉的最短路(起终点只算0.5长,其他算1). 思路: 这 ...
- caioj1496: [视频]基于连通性状态压缩的动态规划问题:Manhattan Wiring
%%%%orz苏大佬 虽然苏大佬的baff吸不得,苏大佬的梦信不得,但是膜苏大佬是少不得的囧 这题还是比较有收获的 哼居然有我不会做的插头DP 自己yy了下,2表示属于2的插头,3表示3的插头 假如当 ...
- 别人整理的DP大全(转)
动态规划 动态规划 容易: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ...
随机推荐
- 常用 css html 样式
CSS基础必学列表 CSS width宽度 CSS height高度 CSS border边框 CSS background背景 CSS sprites背景拼合 CSS float浮动 CSS mar ...
- Linux C语言结构体-学习笔记
Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...
- IO复用——poll系统调用
1.poll函数 #include<poll.h> int poll(struct pollfd* fds, nfds_t ndfs, int timeout) poll函数在一定的时间内 ...
- 2018 ccpc final I. Cockroaches
I. Cockroaches time limit per test6. s memory limit per test256 MB inputstandard input outputstandar ...
- ULINE(插入水平线)
WRITE 'This is Underlined'. ULINE. 输出结果: This is Underlined. ———————————————————
- 『AngularJS』创建 Service
创建服务 Angular提供了几种有用的服务,对于所有的应用来说,你将会发现这些服务对于创建你自己的服务是有用处的.为了创建自己的服务,你应该从通过一个模块(module)注册一个服务工厂方法开始(可 ...
- ardupilot_gazebo仿真(三)
ardupilot_gazebo仿真(三) 标签(空格分隔): 未分类 创建ROS node 实现对无人机的控制(软件在环) MAVROS MAVROS是ROS中的一个能够连接支持MAVLink地面站 ...
- 使用vue和web3创建你的第一个以太坊APP
欢迎回到这个很牛的教程系列的第2部分,在教程中我们亲手构建我们的第一个分布式应用程序. 在第二部分中,我们将介绍VueJS和Vuex的核心概念,并引入web3js以与metamask进行交互. 如果你 ...
- hadoop节点之间通信问题
前天遇到一个hadoop问题,由于之前都是伪分布的情况,没有真正的涉及到集群的环境,最近按照一些资料自己搭建了一个集群环境,三台虚拟机,一个master,两个slave,利用jps查看节点信息,启动了 ...
- User Agent的学习
什么是User-Agent? User-Agent是一个特殊字符串头,被广泛用来标示浏览器客户端的信息,使得服务器能识别客户机使用的操作系统和版本,CPU类型,浏览器及版本,浏览器的渲染引擎,浏览器语 ...