[POJ3133]Manhattan Wiring 插头dp
[POJ3133]Manhattan Wiring 插头dp
原题POJ3133
题意:N*M有障碍矩阵,0可通过,1为障碍,两个2,两个3,求连接两个2和连接两个3的两条不相交路径长度和的最小值(1 <= N, M <= 9).
//——————————————————————–
插头dp
由于路径起点和终点确定,只需要记录插头对应的起点,不需要插头记录连通性。
标号0无插头,1不知起点的插头,2,3分别对应起点为2,3的插头。
***1.对2或者3的格子
(1)没有左,上插头,可增加右插头或下插头,标号与格子的值相同。
(2)只有左插头或只有上插头,并且标号等于格子的值,此格为终点没有右,下插头。
(3)有左,上插头,不合法。
***2.对0的格子
(1)没有左,上插头,可增加右,下插头,标号为2或3,也可跳过此格不放。
(2)只有左插头或只有上插头,延伸插头至右插头或下插头,保持标号不变。
(3)有左,上插头,只有插头标号相同,合并左上插头。
***3.对1的格子
由于不能放,只有没有左,上插头的情况可以转移。
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 15
#define inf 0x7f7f7f7f
#define mod 1000000007
#define HASH 10007
#define STATE 1000100
typedef long long ll;
int n, m;
int code[N];
int mp[N][N];struct HASHMAP
{int head[HASH], next[STATE], size;int f[STATE], state[STATE];void init() {size = 0;memset(head, -1, sizeof(head));}void push(int st, int ans) {int h = st % HASH;for (int i = head[h]; i != -1; i = next[i]) {if (state[i] == st) {f[i] = min(f[i], ans);return;}}state[size] = st;f[size] = ans;next[size] = head[h];head[h] = size++;}
}hm[2];void decode(int st)
{for (int i = m; i >= 0; i--) {code[i] = st & 3;st >>= 2;}
}int encode()
{int st = 0;for (int i = 0; i <= m; i++) {st <<= 2;st |= code[i];}return st;
}void shift()
{for (int i = m; i > 0; i--) {code[i] = code[i-1];}code[0] = 0;
}void dpblank(int r, int c, int cur)
{for (int k = 0; k < hm[cur].size; k++) {decode(hm[cur].state[k]);int up = code[c];int left = code[c-1];if (mp[r][c] == 2 || mp[r][c] == 3) {if ((up == mp[r][c] && !left) || (!up && left == mp[r][c])) {code[c] = code[c-1] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]+1);}if (!up && !left) {if (mp[r][c+1] == 1 || mp[r][c+1] == mp[r][c]) {code[c] = mp[r][c];code[c-1] = 0;hm[cur^1].push(encode(), hm[cur].f[k]+1);}if (mp[r+1][c] == 1 || mp[r+1][c] == mp[r][c]) {code[c-1] = mp[r][c];code[c] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]+1);}} continue;}if (up && left) {if (up == left) {code[c] = code[c-1] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]+1);}}else if (up || left) {int t = up | left;if (mp[r][c+1] == 1 || mp[r][c+1] == t) {code[c] = t;code[c-1] = 0;hm[cur^1].push(encode(), hm[cur].f[k]+1);}if (mp[r+1][c] == 1 || mp[r+1][c] == t) {code[c-1] = t;code[c] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]+1);}}else {code[c] = code[c-1] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]);for (int i = 2; i <= 3; i++) {if ((mp[r][c+1] == 1 || mp[r][c+1] == i) && (mp[r+1][c] == 1 || mp[r+1][c] == i)) {code[c] = i;code[c-1] = i;hm[cur^1].push(encode(), hm[cur].f[k]+1);}}}}
}void dpblock(int r, int c, int cur)
{for (int k = 0; k < hm[cur].size; k++) {decode(hm[cur].state[k]);if (code[c-1] || code[c]) continue;code[c] = code[c-1] = 0;if (c == m) shift();hm[cur^1].push(encode(), hm[cur].f[k]);}
}int main()
{while (cin >> n >> m) {if (!n) break;memset(mp, 0, sizeof(mp));for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> mp[i][j];if (mp[i][j] < 2) mp[i][j] ^= 1;}}int cur = 0;hm[cur].init();hm[cur].push(0, 0);for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {hm[cur^1].init();if (mp[i][j]) dpblank(i, j, cur);else dpblock(i, j, cur);cur ^= 1;}}int ans = 0;for (int i = 0; i < hm[cur].size; i++) {ans += hm[cur].f[i];}if (ans >= 2) ans -= 2;cout << ans << endl;}return 0;
}
[POJ3133]Manhattan Wiring 插头dp相关推荐
- 【POJ3133】Manhattan Wiring 插头DP
原题走这里 看起来就很难的一道题 本题存在一个小陷阱,它看起来像是单回路模型(毕竟是求路径),然而它其实是多回路模型,或者说可以用多回路模型做. 这道题求的是最短距离,那么这就意味着如果出现了多出来的 ...
- POJ 3133 Manhattan Wiring(插头DP)
题目链接:http://poj.org/problem?id=3133 题意:n*m的格子中有两个2和两个3,其余是空白或障碍.找出两条路径分别连接2和3,不经过障碍且不相交.使得两条路径长度和最短? ...
- [Poj3133]Manhattan Wiring (插头DP)
Description 题目大意:给你个N x M(1≤N, M≤9)的矩阵,0表示空地,1表示墙壁,2和3表示两对关键点.现在要求在两对关键点之间建立两条路径,其中两条路径不可相交或者自交(就是重复 ...
- poj3133 Manhattan Wiring
Manhattan Wiring Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 2016 Accepted: 1162 ...
- 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 ...
- POJ3133(插头dp)
传送门:http://poj.org/problem?id=3133 Manhattan Wiring Time Limit: 5000MS Memory Limit: 65536K ...
- [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识--这真的是一种很锻炼人的题型-- 每一道题的状态都不一样 ...
- [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 ...
最新文章
- html中css路径和xpath路径,6.1 HTML的简单介绍和快速获取XPath和CSS路径
- svn数据库自动备份脚本
- BOM的window对象的属性及其方法
- 虚拟主机安装mysql_如何虚拟主机安装mysql
- python 并列条形图_python – 如何绘制具有相同X坐标并排的条形图
- 旷视高调进军AIoT!先砸20亿建智能物流生态,发布机器人协作大脑河图
- 单例设计模式全局缓存accessToken
- js实现视频时间段拖拽编辑
- apms阅卷系统服务器,Win 8系统运行APMS阅卷系统的解决办法
- C语言常见编程题及答案40题
- fileuploads
- G: LZY的计算器
- 微信强制使用本机浏览器打开指定链接是怎么做的
- 生成二维码的三种方式
- sublime text 白色边框方框解决方法
- sql将日期格式化特定的字符串格式
- Java生成名片式的二维码源码分享
- JFinal AOP与Enhancer
- Cesium 卫星轨迹、卫星通信、卫星过境,模拟数据传输。
- ngrok 搭建内网穿透