洛谷P3190 [HNOI2007]神奇游乐园(插头dp)
大概是算第一道自己做出来的插头dp?
(虽然都是照着抄板子的)
(虽然有个地方死活没调出来最后只能看题解才发现自己错在哪里的)
我就当你们都会插头dp了……
因为必须得是一条路径,所以扫描线上的插头得两两对应,要用括号序列
然后分情况讨论一下,记$p1$为当前关键格左边的插头,$p2$为当前关键格上面的插头
$0$表示无插头,$1$表示左括号,$2$表示右括号
1.$p1==0$且$p2==0$
那么很明显我们可以把下方插头设为$1$右方插头设为$2$,就形成一个新的连通块了
然后注意不设任何插头的状态也要转移(我就是在这里坑了一个晚上)
2.$p1!=0$且$p2==0$
那么我们有两种走法,一是直走,那么右插头的值就是原插头的值,一是拐弯,那么下面的插头的值就是左插头的值
3.$p1==0$且$p2!=0$
同上,不多说了
4.$p1==1$且$p2==1$
就是两个左括号撞到一起了,那么把$p2$对应的右括号改成左括号
5.$p1==1$且$p2==2$
这种情况就说明一条路径已经结束了,那么此时如果轮廓线上没有其他任何插头就可以更新答案了
6.$p1==2$且$p2==1$
两条路径在这里汇合,直接合并
7.$p1==2$且$p2==2$
两个右括号撞到一起了,那么把$p1$对应的左括号改成右括号
然后……剩下的看代码好了(似乎我的插头dp写法和很多人不一样诶……)
//minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
const int mod=;
int n,m,c[][];ll ans=-0x3f3f3f3f3f3f3f3f;
struct Ha{
int key[mod],sz,Hash[mod];ll val[mod];
inline void init(){
memset(val,0xef,sizeof(val)),memset(key,-,sizeof(key));
sz=,memset(Hash,,sizeof(Hash));
}
inline void newhash(int id,int state){Hash[id]=++sz,key[sz]=state,val[sz]=-inf;}
ll &operator [](const int state){
for(int i=state%mod;;i=(i+==mod)?:i+){
if(!Hash[i]) newhash(i,state);
if(key[Hash[i]]==state) return val[Hash[i]];
}
}
}f[];
inline int find(int state,int id){return (state>>((id-)<<))&;}
inline void set(int &state,int pos,int val){
pos=(pos-)<<,state|=<<pos,state^=<<pos,state|=val<<pos;
}
int link(int state,int pos){
int cnt=,del=(find(state,pos)==)?:-;
for(int i=pos;i&&i<=m+;i+=del){
int plug=find(state,i);
if(plug==) ++cnt;
else if(plug==) --cnt;
if(!cnt) return i;
}
return -;
}
void solve(int x,int y){
int now=((x-)*m+y)&,last=now^,tot=f[last].sz;
f[now].init();
for(int i=;i<=tot;++i){
int state=f[last].key[i];ll val=f[last].val[i];
int plug1=find(state,y),plug2=find(state,y+);
if(!plug1&&!plug2){
cmax(f[now][state],val);
if(x!=n&&y!=m) set(state,y,),set(state,y+,),cmax(f[now][state],val+c[x][y]);
}
else if(plug1&&!plug2){
if(x!=n) cmax(f[now][state],val+c[x][y]);
if(y!=m) set(state,y,),set(state,y+,plug1),cmax(f[now][state],val+c[x][y]);
}
else if(!plug1&&plug2){
if(y!=m) cmax(f[now][state],val+c[x][y]);
if(x!=n) set(state,y,plug2),set(state,y+,),cmax(f[now][state],val+c[x][y]);
}
else if(plug1==&&plug2==)
set(state,link(state,y+),),set(state,y,),set(state,y+,),cmax(f[now][state],val+c[x][y]);
else if(plug1==&&plug2==){
set(state,y,),set(state,y+,);
if(!state) cmax(ans,val+c[x][y]);
}
else if(plug1==&&plug2==) set(state,y,),set(state,y+,),cmax(f[now][state],val+c[x][y]);
else if(plug1==&&plug2==)
set(state,link(state,y),),set(state,y,),set(state,y+,),cmax(f[now][state],val+c[x][y]);
}
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
scanf("%d",&c[i][j]);
f[].init(),f[][]=;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j) solve(i,j);
if(i!=n){
int now=(i*m)&,tot=f[now].sz;
for(int j=;j<=tot;++j)
f[now].key[j]<<=;
}
}
printf("%lld\n",ans);
return ;
}
洛谷P3190 [HNOI2007]神奇游乐园(插头dp)的更多相关文章
- 洛谷 P3190 [HNOI2007]神奇游乐园 解题报告
P3190 [HNOI2007]神奇游乐园 Description 给你一个 \(m * n\) 的矩阵,每个矩阵内有个权值\(V(i,j)\) (可能为负数),要求找一条回路,使得每个点最多经过一次 ...
- bzoj 1187: [HNOI2007]神奇游乐园 插头dp
1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 668 Solved: 337[Submit][Statu ...
- 【BZOJ1187】[HNOI2007]神奇游乐园 插头DP
[BZOJ1187][HNOI2007]神奇游乐园 Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细 ...
- [HNOI2007][bzoj1187] 神奇游乐园 [插头dp]
题面: 传送门 给定一个四联通棋盘图,每个格子有权值,求一条总权值最大的回路 思路: 插头dp基础教程 棋盘? 回路? n,m<=10? 当然是插头dp啦~\(≧▽≦)/~ 然后发现这道题并不是 ...
- P3190 [HNOI2007]神奇游乐园
传送门 第一道插头 $dp$ 由于讲不清楚所以假装各位早就会插头 $dp$ 了 首先要的是一个闭合回路,所以可以用括号表示法表示状态,然后大力分类讨论 $1.$ 没有右插头和下插头 那么我们可以啥也不 ...
- 洛谷P3272 [SCOI2011]地板(插头dp)
传送门 感谢大佬的教导->这里 容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次. 这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头: 我 ...
- 洛谷P2289 [HNOI2004]邮递员(插头dp)
传送门 太神仙了……讲不来讲不来->这里 //minamoto #include<iostream> #include<cstdio> #include<cstri ...
- [bzoj1187][HNOI2007]神奇游乐园_插头dp
bzoj-1187 HNOI-2007 神奇游乐园 题目大意:经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这 ...
- 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)
洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...
随机推荐
- Java7、Java8 安装卸载问题
win7 系统,同时安装了JDK7和JDK8,卸载了JDK8之后,cmd命令行输入:java -version ,本以为显示java版本1.7,结果弹错:has value '1.7',but '1. ...
- Java for LeetCode 106 Construct Binary Tree from Inorder and Postorder Traversal
Construct Binary Tree from Inorder and Postorder Traversal Total Accepted: 31041 Total Submissions: ...
- Android 破解
一.反编译 默认你的电脑中完好的有java环境 1.下载 Android killer 链接: https://pan.baidu.com/s/1s6lfm8CbdU9ABYEOhdFWxA 提取码 ...
- Posix线程编程指南(1)
这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消. 一.线程创建 1.1 线程与进程相对进程而言,线程是一 ...
- python 多模块文件共享变量
Python import 包的机制是,import进来的和默认的系统的module了,都放在sys.module这个字典里面. 多个py文件再次import的时候,会先去sys.module里面检查 ...
- 洛谷 P2962 [USACO09NOV]灯Lights
题目描述 Bessie and the cows were playing games in the barn, but the power was reset and the lights were ...
- 系列文章--突袭HTML5
学习新的网站构建技术:基于HTML5,但不限于HTML5. 突袭HTML5之Javascript API扩展5 - 其他扩展 突袭HTML5之Javascript API扩展4 - 拖拽 ...
- 用PCA降维 (Principal Component Analysis,主成分分析)
参考资料:Mastering Machine Learning With scikit-learn 降维致力于解决三类问题.第一,降维可以缓解维度灾难问题.第二,降维可以在压缩数据的同时让信息损失最 ...
- poj1456Supermarket——并查集压缩查找
题目:http://poj.org/problem?id=1456 排序+贪心,每次选利润最大的,放在可能的最靠后的日期卖出,利用并查集快速找到下一个符合的日期. 代码如下: #include< ...
- vijos:P1155集合位置(次短路)
描述 每次有大的活动,大家都要在一起“聚一聚”,不管是去好乐迪,还是避风塘,或者汤姆熊,大家都要玩的痛快.还记得心语和花儿在跳舞机上的激情与释放,还记得草草的投篮技艺是如此的高超,还记得狗狗的枪法永远 ...