题目链接:https://vjudge.net/problem/HDU-1964

Pipes

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 987    Accepted Submission(s): 494

Problem Description
The construction of office buildings has become a very standardized task. Pre-fabricated modules are combined according to the customer’s needs, shipped from a faraway factory, and assembled on the construction site. However, there are still some tasks that require careful planning, one example being the routing of pipes for the heating system.

Amodern office building ismade up of squaremodules, one on each floor being a service module from which (among other things) hot water is pumped out to the other modules through the heating pipes. Each module (including the service module) will have heating pipes connecting it to exactly two of its two to four neighboring modules. Thus, the pipes have to run in a circuit, from the service module, visiting each module exactly once, before finally returning to the service module. Due to different properties of the modules, having pipes connecting a pair of adjacent modules comes at different costs. For example, some modules are separated by thick walls, increasing the cost of laying pipes. Your task is to, given a description of a floor of an office building, decide the cheapest way to route the heating pipes.

 
Input
The first line of input contains a single integer, stating the number of floors to handle. Then follow n floor descriptions, each beginning on a new line with two integers, 2 <= r <= 10 and 2 <= c <= 10, defining the size of the floor – r-by-c modules. Beginning on the next line follows a floor description in ASCII format, in total 2r + 1 rows, each with 2c + 2 characters, including the final newline. All floors are perfectly rectangular, and will always have an even number of modules. All interior walls are represented by numeric characters, ’0’ to ’9’, indicating the cost of routing pipes through the wall (see sample input).
 
Output
For each test case, output a single line with the cost of the cheapest route.
 
Sample Input
3
4 3
#######
# 2 3 #
#1#9#1#
# 2 3 #
#1#7#1#
# 5 3 #
#1#9#1#
# 2 3 #
#######
4 4
#########
# 2 3 3 #
#1#9#1#4#
# 2 3 6 #
#1#7#1#5#
# 5 3 1 #
#1#9#1#7#
# 2 3 0 #
#########
2 2
#####
# 1 #
#2#3#
# 4 #
#####
 
Sample Output
28
45
10
 
Source
 
Recommend
wangye

题意:

给出一个n*m(n、m<=10)的棋盘,对于一个格子,分别给出它与四个方向相连所需要的花费(即打穿这堵墙所需的花费),求一个回路使得这个回路经过所有的格子刚好一次,且花费是最小的,输出最小花费。

题解:

与此题(URAL1519 Formula 1)无异,只不过把统计个数改成求最小值。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5;
const int HASH = 1e4; int n, m, last_x, last_y;
bool maze[][];
int down_cost[][], ri_cost[][]; struct
{
int size, head[HASH], next[MAXN];
LL state[MAXN];
int cost[MAXN]; void init()
{
size = ;
memset(head, -, sizeof(head));
} void insert(LL status, int Cost)
{
int u = status%HASH;
for(int i = head[u]; i!=-; i = next[i])
{
if(state[i]==status)
{
cost[i] = min(cost[i], Cost);
return;
}
}
state[size] = status;
cost[size] = Cost;
next[size] = head[u];
head[u] = size++;
} }Hash_map[]; struct
{
int code[];
LL encode(int m)
{
LL status = ;
int id[], cnt = ;
memset(id, -, sizeof(id));
id[] = ;
for(int i = m; i>=; i--)
{
if(id[code[i]]==-) id[code[i]] = ++cnt;
code[i] = id[code[i]];
status <<= ;
status += code[i];
}
return status;
} void decode(int m, LL status)
{
memset(code, , sizeof(code));
for(int i = ; i<=m; i++)
{
code[i] = status&;
status >>= ;
}
} void shift(int m)
{
for(int i = m-; i>=; i--)
code[i+] = code[i];
code[] = ;
} }Line; //插头的花费在新建的时候加进去
void transfer(int i, int j, int cur)
{
for(int k = ; k<Hash_map[cur].size; k++)
{
LL status = Hash_map[cur].state[k];
LL Cost = Hash_map[cur].cost[k];
Line.decode(m, status);
int up = Line.code[j];
int left = Line.code[j-]; if(!up && !left)
{
if(maze[i+][j] && maze[i][j+])
{
Line.code[j] = Line.code[j-] = ; //最多只有5个连通分量
Hash_map[cur^].insert(Line.encode(m), Cost+down_cost[i][j]+ri_cost[i][j]);
}
}
else if( (left&&!up) || (!left&&up) )
{
int line = left?left:up;
if(maze[i][j+])
{
Line.code[j-] = ;
Line.code[j] = line;
Hash_map[cur^].insert(Line.encode(m), Cost+ri_cost[i][j]);
}
if(maze[i+][j])
{
Line.code[j-] = line;
Line.code[j] = ;
if(j==m) Line.shift(m);
Hash_map[cur^].insert(Line.encode(m), Cost+down_cost[i][j]);
}
}
else
{
if(up!=left)
{
Line.code[j] = Line.code[j-] = ;
for(int t = ; t<=m; t++)
if(Line.code[t]==up)
Line.code[t] = left;
if(j==m) Line.shift(m);
Hash_map[cur^].insert(Line.encode(m), Cost);
}
else if(i==last_x && j==last_y)
{
Line.code[j] = Line.code[j-] = ;
if(j==m) Line.shift(m);
Hash_map[cur^].insert(Line.encode(m), Cost);
}
}
}
} int main()
{
int T;
char str[];
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m); getchar();
memset(maze, false, sizeof(maze));
for(int i = ; i<=n; i++)
for(int j = ; j<=m; j++)
maze[i][j] = true; gets(str);
for(int i = ; i<n; i++)
{
gets(str);
for(int j = ; j<m; j++)
ri_cost[i][j] = str[j*] - '';
gets(str);
for(int j = ; j<=m; j++)
down_cost[i][j] = str[j*-] - '';
}
gets(str);
for(int j = ; j<m; j++)
ri_cost[n][j] = str[j*] - '';
gets(str);
last_x = n;
last_y = m; int cur = ;
Hash_map[cur].init();
Hash_map[cur].insert(, );
for(int i = ; i<=n; i++)
for(int j = ; j<=m; j++)
{
Hash_map[cur^].init();
transfer(i, j, cur);
cur ^= ;
} LL last_status = ;
LL ans = Hash_map[cur].size?Hash_map[cur].cost[last_status]:;
printf("%d\n", ans);
}
}

HDU1964 Pipes —— 插头DP的更多相关文章

  1. hdu1964之插头DP求最优值

    Pipes Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  2. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  3. 插头dp练习

    最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...

  4. 插头dp

    插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...

  5. HDU 4113 Construct the Great Wall(插头dp)

    好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...

  6. HDU 4949 Light(插头dp、位运算)

    比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...

  7. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  8. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

  9. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

随机推荐

  1. COdevs 天梯 水题系列

    1203 判断浮点数是否相等 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 给出两个浮点数,请你判断这两个浮点数是否相等 输入 ...

  2. HDU4768:Flyer [ 二分的奇妙应用 好题 ]

    传送门 Flyer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. iOS 取应用版本

    
// 应用网址 返回字典中有多种数据 NSString *urlString2 = [NSString stringWithFormat: @"%@", @"http: ...

  4. govalidator----结构体tag验证

    github地址:https://github.com/asaskevich/govalidator govalidator支持内置支持的验证tag和自定义验证tag: package main im ...

  5. 洛谷——P1290 欧几里德的游戏

    P1290 欧几里德的游戏 题目描述 欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的 ...

  6. python多线程(一)

    原文:http://www.pythonclub.org/python-basic/threading 一.python多线程thread和threading实现 python是支持多线程的,并且是n ...

  7. 新建JRapid项目(idea创建maven多模块项目)

    1.第一步,新建项目(Create New Project) 2.parent项目,不勾选“Crate from archetype”,直接单击“Next”. 3.groupid填写com.codin ...

  8. maven最小配置

    将参与项目开发的开发人员的用户名及邮箱捆绑在一起,在code review是更加方便的进行版本管控: 1.配置user,name和user,email命令: $ git config --global ...

  9. [ACM] ZOJ 3725 Painting Storages (DP计数+组合)

    Painting Storages Time Limit: 2 Seconds      Memory Limit: 65536 KB There is a straight highway with ...

  10. Android——ListView优化

    1.ListView基本概念 列表显示需要三个元素: ListView:用来展示列表的View. 适配器:用来把数据映射到ListView上 数据:具体的将被映射的字符串,图片或基本组件 适配器类型分 ...