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三个函数以 ...
随机推荐
- Hibernate的session.createSQLQuery的几种查询方式
当我们用HQL进行子查询的时候,如select * from Tree where pid in (select id from Tree,此时HIBERANTE就会报错,说什么*号错误之类的.但如果 ...
- OS__信号量(semaphore)PV操作
信号量的概念 1.信号量的类型定义 信号量(semaphore)的数据结构为记录型数据结构一个值和一个指针,指针指向等待该信号量的下一个进程.信号量的值与相应资源的使用情况有关,在操作系统中,信号量用 ...
- linux之打包压缩命令
tar:主选项:[一条命令以下5个参数只能有一个]-c: --create 新建一个压缩文档,即打包-x: --extract,--get解压文件-t: --list,查看压缩文档里的文件目录-r:- ...
- 反射invoke()方法
invoke()方法: 主要是为了类反射,可以在不知道具体类的情况下,根据配置字符串去调用一个类的方法.最简单的方法是可以把方法参数化. main.invoke(): 比如Test类里有 ...
- Flutter实战视频-移动电商-35.列表页_上拉加载更多制作
35.列表页_上拉加载更多制作 右侧列表上拉加载配合类别的切换 上拉加载需要一个page参数,当点击大类或者小类的时候,这个page就要变成1 provide内定义参数 首先我们需要定义一个page的 ...
- Eclipse+Maven+TestNg+ReportNg 生成测试报告
http://blog.csdn.net/a542551042/article/details/46729585
- E20190407-hm
conclude vt. 推断; 结束,终止; 议定; vi. 终了; 作出决定或达成协议; interjection n. 叹词,感叹词; definitely adv. 明确地; 确切地; ...
- HDU3038【种类并查集】
题意: 给出m组区间[a,b],以及其区间的和,问有矛盾的有几组: 思路: 种类并查集. 主要是几个关系:同类元素的关系,父亲与儿子的关系,不同类元素的关系: 我们可以类似看作一个前缀和,sum[x] ...
- IT兄弟连 JavaWeb教程 EL表达式中的内置对象
EL语言定义了11个隐含对象,它们都是java.util.Map类型,网页制作者可通过它们来便捷地访问Web应用中的特定数据.表1对这11个隐含对象做了说明. 1 EL表达式中的内置对象 这11个隐 ...
- css定位-position
前言 定位的目的就是把元素摆放到指定的位置. 定位上下文:定位元素的大小,位置都是相对于定位上下文的. position属性值有5个值 static:所有有元素定位默认的初始值都是static.就是不 ...