传送门

第一道插头 $dp$

由于讲不清楚所以假装各位早就会插头 $dp$ 了

首先要的是一个闭合回路,所以可以用括号表示法表示状态,然后大力分类讨论

$1.$ 没有右插头和下插头

那么我们可以啥也不干,或者加一个右插头和下插头

$2.$ 只有下插头没有右插头

那么我们可以要把下插头继续延伸,可以向下或者向右

$3.$ 只有右插头没有下插头:

同理我们可以往下或者往右延伸

$4.$ 右插头和下插头都有:这个又要分情况讨论

  $a.$ 插头都是左括号,那么要把两个联通还要把右边原来匹配的右括号改成左括号

  

  $b.$ 插头都是右括号,那么要把两个联通还要把左边原本匹配的左括号改成右括号

  

  $c.$ 右插头是左括号,下插头是右括号,那么直接联通即可,不需要改变其他括号

  

  $d.$ 右插头是右括号,下插头是左括号,如果联通则一定形成一个闭合回路,那么如果其他地方没有插头则直接把当前状态计入答案,否则此状态不合法,不用延伸状态(右图是一种不合法状态)

  

然后根据考虑到的所有状态慢慢转移即可......

因为数据比较大所以用滚动数组和哈希表维护状态,状态在加入哈希表时更新

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=3e5;
const ll INF=1e18;
int n,m,a[][],bit[],cur,pre;
ll f[][N+],Ans=-INF;
int fir[N+],from[N+],to[][N+],cntt[];//哈希表
inline void insert(int sta,ll val)//插入状态并更新f
{
int p=sta%N;
for(int i=fir[p];i;i=from[i])
{
if(to[cur][i]!=sta) continue;
f[cur][i]=max(f[cur][i],val); return;
}
from[++cntt[cur]]=fir[p]; fir[p]=cntt[cur];
to[cur][cntt[cur]]=sta; f[cur][cntt[cur]]=val;
}
void DP()
{
cntt[cur]=; int now,down,right; ll val;
for(int i=;i<=n;i++)//枚举行
{
for(int j=;j<=cntt[cur];j++) to[cur][j]<<=;//每一行末尾,状态统一左移四进制下的一位
for(int j=;j<=m;j++)//枚举列
{
pre=cur; cur^=; cntt[cur]=; memset(fir,,sizeof(fir));//清空哈希表
for(int k=;k<=cntt[pre];k++)//枚举上一行的状态
{
now=to[pre][k]; val=f[pre][k];
right=(now>>bit[j-])%; down=(now>>bit[j])%;//提出插头状态
if(!down&&!right)//没有插头
{
insert(now,val);//继续没有插头
if(j!=m) insert(now+(<<bit[j-])+((<<bit[j])<<),val+a[i][j]);//多一个右插头和下插头
}
if(down&&!right)//只有下插头
{
insert(now-down*(<<bit[j])+down*(<<bit[j-]),val+a[i][j]);//向下延伸
if(j!=m) insert(now,val+a[i][j]);//向右延伸
}
if(!down&&right)//只有右插头
{
insert(now,val+a[i][j]);//向下延伸
if(j!=m) insert(now-right*(<<bit[j-])+right*(<<bit[j]),val+a[i][j]);//向右延伸
}
if(down==&&right==)//插头为'(('
{
int cnt=;
for(int l=j+;l<=m;l++)//找到右边第一个和当前下插头匹配的')'
{
if((now>>bit[l])%==) cnt++;
if((now>>bit[l])%==) cnt--;
if(!cnt)
{
insert(now-(<<bit[l])-(<<bit[j-])-(<<bit[j]),val+a[i][j]);//联通并改')'为'('
break;
}
}
}
if(down==&&right==)//插头为'))'
{
int cnt=;
for(int l=j-;l>=;l--)//找到左边第一个和当前右插头匹配的'('
{
if((now>>bit[l])%==) cnt--;
if((now>>bit[l])%==) cnt++;
if(!cnt)
{
insert(now+(<<bit[l])-((<<bit[j-])<<)-((<<bit[j])<<),val+a[i][j]);//联通并改'('为')'
break;
}
}
}
if(down==&&right==)//')('
insert(now-((<<bit[j-])<<)-(<<bit[j]),val+a[i][j]);//直接联通即可
if(down==&&right==)//'()'
if(now==((<<bit[j])<<)+(<<bit[j-]))//当前状态只有这两个插头
Ans=max(Ans,val+a[i][j]);//统计答案
}
}
}
}
int main()
{
n=read(),m=read();
for(int i=;i<=;i++) bit[i]=(i<<);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) a[i][j]=read();
DP();
printf("%lld\n",Ans);
return ;
}

P3190 [HNOI2007]神奇游乐园的更多相关文章

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

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

  2. 洛谷P3190 [HNOI2007]神奇游乐园(插头dp)

    传送门 大概是算第一道自己做出来的插头dp? (虽然都是照着抄板子的) (虽然有个地方死活没调出来最后只能看题解才发现自己错在哪里的) 我就当你们都会插头dp了…… 因为必须得是一条路径,所以扫描线上 ...

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

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

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

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

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

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

  6. 1187: [HNOI2007]神奇游乐园 - BZOJ

    Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计. ...

  7. bzoj:1187: [HNOI2007]神奇游乐园

    Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计. ...

  8. [bzoj1187][HNOI2007]神奇游乐园

    来自FallDream的博客,未经允许,请勿转载,谢谢, 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一 ...

  9. BZOJ1187 [HNOI2007]神奇游乐园(插头dp)

    麻麻我会写插头dp了! 推荐陈丹琦论文:https://wenku.baidu.com/view/3e90d32b453610661ed9f4bd.html 破题调一年 #include <cs ...

随机推荐

  1. ASP.NET MVC Ajax下载文件(使用NPOI向现有的excel模板文件里面添加数据)

    View Html.DevExpress().Button(DevExpressButtonHelper.AddButton(ViewBag.Form, "Export", &qu ...

  2. csp-s2019 AFO记

    DAY 0 上午出发前大家都很颓废的样子. 我因为还没有实现刷完NOIP专题的所有题的目标而去憨比的学DDP. 最后还是不会,保卫王国是写不成了…… 该走了,学校领导来开了个欢送会,祝福我们从里WA到 ...

  3. logstash搭建

    logstash就是一个具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端:与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供里很多功能强大的滤网以满 ...

  4. sqli-labs29-31关Background-6 服务器(两层)架构

    首先介绍一下29,30,31这三关的基本情况: 服务器端有两个部分:第一部分为tomcat为引擎的jsp型服务器,第二部分为apache为引擎的php服务器,真正提供web服务的是php服务器.工作流 ...

  5. Android传感器【转】

    本文转载自:http://blog.csdn.net/ffmxnjm/article/details/52101592?locationNum=3&fps=1 传感器的意义 事实上,目前智能手 ...

  6. Sqlserver 创建账号

    下面是通过脚本创建账号,创建一个appuser 的账号,密码:123456,可操作的DB:TEST 赋予权限,增删改查,操作视图,存储过程.当然当前的账号要有足够的权限. create login a ...

  7. ssd写入量剩余读写次数怎么查

    固态硬盘ssd写入量剩余读写次数怎么查 为什么要查固态硬盘的写入量呢,主要是因为闪存是有写入次数限制的,所以查次数就是看看寿命还有多少,说白了这是对耐久度的一点担忧.其实目前原厂出品的固态硬盘,即便是 ...

  8. 微博获取原图时重定向到图片的url

    微博获取原图时重定向到图片的url,所以获取的是乱码 jsoup默认是执行重定向的. //根据Url获取页面对应的Document public static Document getDoc1(Str ...

  9. python正则表达式 分割字符串

    使用或 标准的正则表达式有小括号,但是python的没有 # -*- coding: utf-8 -*- import sys import re import sys reload(sys) sys ...

  10. 学习Linux的基础网站

    http://c.biancheng.net/view/726.html