传送门

大概是算第一道自己做出来的插头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)的更多相关文章

  1. 洛谷 P3190 [HNOI2007]神奇游乐园 解题报告

    P3190 [HNOI2007]神奇游乐园 Description 给你一个 \(m * n\) 的矩阵,每个矩阵内有个权值\(V(i,j)\) (可能为负数),要求找一条回路,使得每个点最多经过一次 ...

  2. bzoj 1187: [HNOI2007]神奇游乐园 插头dp

    1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 668  Solved: 337[Submit][Statu ...

  3. 【BZOJ1187】[HNOI2007]神奇游乐园 插头DP

    [BZOJ1187][HNOI2007]神奇游乐园 Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细 ...

  4. [HNOI2007][bzoj1187] 神奇游乐园 [插头dp]

    题面: 传送门 给定一个四联通棋盘图,每个格子有权值,求一条总权值最大的回路 思路: 插头dp基础教程 棋盘? 回路? n,m<=10? 当然是插头dp啦~\(≧▽≦)/~ 然后发现这道题并不是 ...

  5. P3190 [HNOI2007]神奇游乐园

    传送门 第一道插头 $dp$ 由于讲不清楚所以假装各位早就会插头 $dp$ 了 首先要的是一个闭合回路,所以可以用括号表示法表示状态,然后大力分类讨论 $1.$ 没有右插头和下插头 那么我们可以啥也不 ...

  6. 洛谷P3272 [SCOI2011]地板(插头dp)

    传送门 感谢大佬的教导->这里 容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次. 这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头: 我 ...

  7. 洛谷P2289 [HNOI2004]邮递员(插头dp)

    传送门 太神仙了……讲不来讲不来->这里 //minamoto #include<iostream> #include<cstdio> #include<cstri ...

  8. [bzoj1187][HNOI2007]神奇游乐园_插头dp

    bzoj-1187 HNOI-2007 神奇游乐园 题目大意:经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这 ...

  9. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

随机推荐

  1. Spark与缓存

    预期成果 1.1   当前问题 当前以图搜图应用存在的问题: 当前使用spark RDD方案无法达到数据实时加载(每10分钟加载一次,虽然可配,但太短可能会有问题) Spark RDD内存会被分为两部 ...

  2. stm32.cube介绍

    stm32.cube(一)——系统架构及目录结构 stm32.cube(二)——HAL结构及初始化 stm32.cube(三)——HAL.GPIO stm32.cube(四)——HAL.ADC stm ...

  3. Quartz时SLF4J错误

    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-o ...

  4. 20145239 《Java程序设计》实验三 实验报告

    详见我的parter20145224的博客:http://www.cnblogs.com/20145224kevs/p/5428892.html 感想:这次的实验看似容易,但很多点都需要注意,比如开源 ...

  5. Shell 特殊位置参数的变量

    $0 -- 获取当前执行shell脚本的 文件名 $n -- 获取当前执行shell脚本的 第n个参数 $# -- 获取当前执行shell脚本的 带的参数个数 $? -- 获取执行上一个指令的执行状态 ...

  6. 学习html第一天

    网站本身就是软件,软件:一种具有特定功能的程序指令的集合 C/S:C客户端-->S服务器  由程序员开发  客户去下载升级安装,比如魔兽世界 B/S:B浏览器-->S服务器  由程序员开发 ...

  7. 分享知识-快乐自己:SpringMvc中的四种数据源及相关配置(整合快速集成开发)

     数据库连接: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://39.105.105.186:3306/SpringMybatis?us ...

  8. ctypes模块与pywin32模块

    ctypes模块: 主要用于调用c动态链接库. 1.聊聊Python ctypes模块 2.ctypes模块管理 相关网址: pywin32模块: 用于访问win32API函数(win32api模块) ...

  9. CodeForces - 660F:Bear and Bowling 4(DP+斜率优化)

    Limak is an old brown bear. He often goes bowling with his friends. Today he feels really good and t ...

  10. python+selenium自动化测试环境搭建

    selenium 是一个web的自动化测试工具,不少学习功能自动化的同学开始首选selenium ,相因为它相比QTP有诸多有点: *  免费,也不用再为破解QTP而大伤脑筋 *  小巧,对于不同的语 ...