[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相关推荐

  1. 【POJ3133】Manhattan Wiring 插头DP

    原题走这里 看起来就很难的一道题 本题存在一个小陷阱,它看起来像是单回路模型(毕竟是求路径),然而它其实是多回路模型,或者说可以用多回路模型做. 这道题求的是最短距离,那么这就意味着如果出现了多出来的 ...

  2. POJ 3133 Manhattan Wiring(插头DP)

    题目链接:http://poj.org/problem?id=3133 题意:n*m的格子中有两个2和两个3,其余是空白或障碍.找出两条路径分别连接2和3,不经过障碍且不相交.使得两条路径长度和最短? ...

  3. [Poj3133]Manhattan Wiring (插头DP)

    Description 题目大意:给你个N x M(1≤N, M≤9)的矩阵,0表示空地,1表示墙壁,2和3表示两对关键点.现在要求在两对关键点之间建立两条路径,其中两条路径不可相交或者自交(就是重复 ...

  4. poj3133 Manhattan Wiring

    Manhattan Wiring Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 2016   Accepted: 1162 ...

  5. POJ 3133 Manhattan Wiring (插头DP)

    Manhattan Wiring Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 1110   Accepted: 634 D ...

  6. POJ 3133 Manhattan Wiring(限制匹配的插头DP)

    Manhattan Wiring Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 1921   Accepted: 1130 ...

  7. POJ3133(插头dp)

    传送门:http://poj.org/problem?id=3133 Manhattan Wiring Time Limit: 5000MS   Memory Limit: 65536K       ...

  8. [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识--这真的是一种很锻炼人的题型-- 每一道题的状态都不一样 ...

  9. [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 ...

最新文章

  1. html中css路径和xpath路径,6.1 HTML的简单介绍和快速获取XPath和CSS路径
  2. svn数据库自动备份脚本
  3. BOM的window对象的属性及其方法
  4. 虚拟主机安装mysql_如何虚拟主机安装mysql
  5. python 并列条形图_python – 如何绘制具有相同X坐标并排的条形图
  6. 旷视高调进军AIoT!先砸20亿建智能物流生态,发布机器人协作大脑河图
  7. 单例设计模式全局缓存accessToken
  8. js实现视频时间段拖拽编辑
  9. apms阅卷系统服务器,Win 8系统运行APMS阅卷系统的解决办法
  10. C语言常见编程题及答案40题
  11. fileuploads
  12. G: LZY的计算器
  13. 微信强制使用本机浏览器打开指定链接是怎么做的
  14. 生成二维码的三种方式
  15. sublime text 白色边框方框解决方法
  16. sql将日期格式化特定的字符串格式
  17. Java生成名片式的二维码源码分享
  18. JFinal AOP与Enhancer
  19. Cesium 卫星轨迹、卫星通信、卫星过境,模拟数据传输。
  20. ngrok 搭建内网穿透

热门文章

  1. 基于Java的在线作业系统
  2. 80后还有几人记得游褒禅山记?
  3. 谷哥学术2022年2月份资源分享下载列表 12/20
  4. Nvivo11制作并导入时间脚本
  5. 在谷歌浏览器中调试js代码
  6. 第1134期AI100_机器学习日报(2017-10-26)
  7. 小白学 Python 爬虫(42):春节去哪里玩(系列终篇)
  8. win10改win7后usb键盘鼠标都不能用
  9. 数控机床手动编程能否用计算机验证,数控机床编程与操作,手工编程和自动编程...
  10. 这些最常用的Linux命令都不会,你怎么敢去面试?