HDU 1964 Pipes (插头DP,变形)
题意:给一个n*m的矩阵,每个格子都是必走的,且无障碍格子,每对格子之间都有一个花费,问哈密顿回路的最小花费。
思路:
这个和Formula1差不多,只是求得是最小花费,这只需要修改一下DP值为花费就行了,主要是在创建新括号,以及延续一个插头的时候花费,因为可能上一个格子有多个状态都可以转移到本格子的同一状态,那么同一个格子中的同一状态的DP值取最小值即可。
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=; int g[N][N], cur, n, m;
struct Hash_Map
{
static const int mod=;
static const int NN=;
int head[mod]; //桶指针
int next[NN]; //记录链的信息
LL status[NN]; //状态
LL value[NN]; //状态对应的DP值。
int size; void clear() //清除哈希表中的状态
{
memset(head, -, sizeof(head));
size = ;
} void insert(LL st, LL val) //插入状态st的值为val
{
int h = st%mod;
for(int i=head[h]; ~i; i=next[i])
if(status[i] == st) //这个状态已经存在,累加进去。
{
value[i] = min(value[i], val);
return ;
}
status[size]= st; //找不到状态st,则插入st。
value[size] = val;
next[size] = head[h] ; //新插入的元素在队头
head[h] = size++;
}
}hashmap[]; inline int getbit(LL s,int pos) //取出状态s的第pos个插头
{
return (s>>*pos)&;
}
inline int setbit(LL s,int pos,int bit) //将状态s的第pos个插头设置为bit
{
if(s&(<<*pos )) s^=<<(*pos);
if(s&(<<(*pos+))) s^=<<(*pos+);
return (s|(bit<<*pos));
} int Fr(LL s,int pos,int bit) //寻找状态s的第pos个插头对应的右括号。
{
int cnt=;
for(pos+=; pos<m; pos++)
{
if(getbit(s, pos)==-bit) cnt++;
if(getbit(s, pos)==bit) cnt--;
if(cnt==-) return setbit(s, pos, -bit);
}
}
int Fl(LL s,int pos,int bit) //寻找状态s的第pos个插头对应的左括号。
{
int cnt=;
for(pos--; pos>=; pos--)
{
if(getbit(s, pos)==-bit) cnt++;
if(getbit(s, pos)==bit) cnt--;
if( cnt==-) return setbit(s, pos, -bit);
}
} void DP(int i,int j)
{
LL t;
for(int k=; k<hashmap[cur^].size; k++)
{
LL s=hashmap[cur^].status[k];
LL v=hashmap[cur^].value[k];
int R=getbit(s, j), D=getbit(s, j+);
if(R && D) //两个括号
{
t=(setbit(s,j,)&setbit(s,j+,));
if(R==D) //同个方向的括号
{
if(R==) t=Fr(t, j, ); //要改
else t=Fl(t, j, );
hashmap[cur].insert(t, v);
}
else if( R== && D== ) //不同的连通分量
hashmap[cur].insert(t, v);
else if( i+==n && j+==m && t== ) //终点才能闭合
hashmap[cur].insert(t, v);
}
else if(R || D) //仅1个括号
{
if(R) //右插头
{
if(i+<n ) hashmap[cur].insert(s, v+g[i*m+j+][i*m+m+j+]);//往下
if(j+<m ) hashmap[cur].insert(setbit(setbit(s,j,), j+, R), v+g[i*m+j+][i*m+j+]);//往右
}
else //下插头
{
if(j+<m ) hashmap[cur].insert(s, v+g[i*m+j+][i*m+j+]); //往右
if(i+<n ) hashmap[cur].insert(setbit(setbit(s,j+,), j, D), v+g[i*m+j+][i*m+m+j+]);//往下
}
}
else //无括号
{
if( j+<m && i+<n ) //新括号
{
v+=g[i*m+j+][i*m+m+j+]; //下
v+=g[i*m+j+][i*m+j+]; //右
hashmap[cur].insert( setbit(s,j,)|setbit(s,j+,), v);
}
}
}
} void cal()
{
for(int i=; i<n; i++)
{
cur^=;
hashmap[cur].clear();
for(int j=; j<hashmap[cur^].size; j++) //新行,需要左移一下状态。
hashmap[cur].insert( hashmap[cur^].status[j]<<, hashmap[cur^].value[j] );
for(int j=; j<m; j++)
{
cur^=;
hashmap[cur].clear();
DP(i,j);
}
}
}
LL print()
{
for(int i=; i<hashmap[cur].size; i++)
if(hashmap[cur].status[i]==)
return hashmap[cur].value[i];
return ;
} int main()
{
//freopen("input.txt", "r", stdin);
int t, Case=;
cin>>t;
while(t--)
{
memset(g,,sizeof(g));
n=m=cur=;
scanf("%d%d",&n,&m);
for(int i=; i<n; i++) //输入
{
for(int j=; j<m; j++) //左右
{
char c=getchar();
if(isdigit(c))
g[i*m-m+j][i*m-m+j+]=g[i*m-m+j+][i*m-m+j]=c-'';
else j--;
}
for(int j=; j<=m; j++) //上下
{
char c=getchar();
if(isdigit(c))
g[i*m-m+j][i*m+j]=g[i*m+j][i*m-m+j]=c-'';
else j--;
}
}
for(int j=; j<m; j++) //最后一行:左右
{
char c=getchar();
if(isdigit(c))
g[n*m-m+j][n*m-m+j+]=g[n*m-m+j+][n*m-m+j]=c-'';
else j--;
}
char s[];
scanf("%s%s",s,s);//多余 hashmap[cur].clear();
hashmap[cur].insert(, ); //初始状态:花费0
cal();
cout<<print()<<endl;
}
return ;
}
AC代码
HDU 1964 Pipes (插头DP,变形)的更多相关文章
- HDU1964 Pipes —— 插头DP
题目链接:https://vjudge.net/problem/HDU-1964 Pipes Time Limit: 5000/1000 MS (Java/Others) Memory Limi ...
- HDU 4285 circuits( 插头dp , k回路 )
circuits Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- 插头dp练习
最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...
- HDU 3377 Plan (插头DP,变形)
题意:有一个n*m的矩阵,每个格子中有一个值(可能负值),要从左上角走到右下角,求路径的最大花费. 思路: 除了起点和终点外,其他的点可以走,也可以不走. (2)我用的是括号表示法,所以起始状态为') ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- 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 ...
- hdu 1693 Eat the Trees——插头DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...
- HDU 4949 Light(插头dp、位运算)
比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...
随机推荐
- 探究c++默认初始化
按照c++ primer 5th第40页的描述,如果定义变量时没有指定初值,则变量被默认初始化,此时变量被赋予了“默认值”. 根据变量定义的位置,分为两种情况: 1.定义于任何函数体之外的变量被初始化 ...
- CF-799B
B. T-shirt buying time limit per test 3 seconds memory limit per test 256 megabytes input standard i ...
- python 网络编程(网络基础之网络协议篇)
前言 C/S B/S 架构 client<----->server browser<--->server 学习socket编程就是要编写一个客户端软件和服务端软件,然后实现服 ...
- UVa 557 Burger (概率+递推)
题意:有 n 个牛肉堡和 n 个鸡肉堡给 2n 个客人吃,在吃之前抛硬币来决定吃什么,如果剩下的汉堡一样,就不用投了,求最后两个人吃到相同的概率. 析:由于正面考虑还要要不要投硬币,太麻烦,所以我们先 ...
- 【转】NET中管理数字证书(Digital Certificate)的一些类
http://blog.csdn.net/bat800/article/details/2314510 http://blog.csdn.net/zjlovety/article/details/72 ...
- opensns入门
1.公共控制器 AdminController.class.php 2.控制器中 使用 $list = $this->lists(); 可以获取数据表中的数据,相当于基本的查询 3.将数据查询 ...
- tinyxml一些应注意的问题
今天在对使用tinyxml库的程序调试的时候,出现的一些问题让人很纠结,特记以此... 在对TixmlDocument创建时我是用new创建的,然后在用完之后我用delete释放掉,可是用gdb调试 ...
- AtCoder Regular Contest 061 E - すぬけ君の地下鉄旅行【最短路】
具体题解又要搬大哥的了,嘿嘿~ 请点击:G点我 这道题目的难点就是同一家公司的路直接走不需要再花费,然后多了一个公司这个东西,这个不像是边的副权值(瞎说的)之类的东西,这是对于路来说的,路的属性... ...
- GPU渲染管线与shader
1 几何阶段(顶点shader处理这部分) 模型坐标空间-世界坐标空间-观察坐标空间-屏幕坐标空间 其中从观察空间 到 屏幕空间需要经过3步(CVV单位立方体,规范立方体) a用透视变换矩阵把顶点从视 ...
- Java的12个语法糖【转】
本文转载自公众号 Hollis 原创: 会反编译的 Hollis 侵权删 本文从 Java 编译原理角度,深入字节码及 class 文件,抽丝剥茧,了解 Java 中的语法糖原理及用法,帮助大家在学 ...