P3190 [HNOI2007]神奇游乐园
第一道插头 $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]神奇游乐园的更多相关文章
- 洛谷 P3190 [HNOI2007]神奇游乐园 解题报告
P3190 [HNOI2007]神奇游乐园 Description 给你一个 \(m * n\) 的矩阵,每个矩阵内有个权值\(V(i,j)\) (可能为负数),要求找一条回路,使得每个点最多经过一次 ...
- 洛谷P3190 [HNOI2007]神奇游乐园(插头dp)
传送门 大概是算第一道自己做出来的插头dp? (虽然都是照着抄板子的) (虽然有个地方死活没调出来最后只能看题解才发现自己错在哪里的) 我就当你们都会插头dp了…… 因为必须得是一条路径,所以扫描线上 ...
- 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发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细 ...
- [bzoj1187][HNOI2007]神奇游乐园_插头dp
bzoj-1187 HNOI-2007 神奇游乐园 题目大意:经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这 ...
- 1187: [HNOI2007]神奇游乐园 - BZOJ
Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计. ...
- bzoj:1187: [HNOI2007]神奇游乐园
Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计. ...
- [bzoj1187][HNOI2007]神奇游乐园
来自FallDream的博客,未经允许,请勿转载,谢谢, 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一 ...
- BZOJ1187 [HNOI2007]神奇游乐园(插头dp)
麻麻我会写插头dp了! 推荐陈丹琦论文:https://wenku.baidu.com/view/3e90d32b453610661ed9f4bd.html 破题调一年 #include <cs ...
随机推荐
- CDOJ 1061 C - 秋实大哥与战争 STL set 迭代器
题目链接: C - 秋实大哥与战争 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu Sub ...
- Kubernetes Deployment故障排除图解指南
个人K8s还在学习中,相关博客还没有写,准备学第二遍再开始学,发现这篇文章挺好,先转载一下. 原创: 白明的赞赏账户 下面是一个示意图,可帮助你调试Kubernetes Deployment(你可以 ...
- tesseract 4.0 使用
https://blog.csdn.net/andylanzhiyong/article/details/81807425 官方例子: https://github.com/tesseract-ocr ...
- Http请求详解(转)----请求+响应各字段详解
参考HTTP深入浅出http请求(转)-----http请求的过程和实现机制 1. HTTP请求格式 首先介绍HTTP协议:超文本传输协议(HTTP,HyperText Transfer Protoc ...
- LINK : fatal error LNK1104: 无法打开文件“qtmaind.lib”
LINK : fatal error LNK1104: 无法打开文件"qtmaind.lib" VS2019+QT5.13出现该问题,可以尝试这样解决. 1.找打qtmaind.l ...
- 每日踩坑 2019-07-30 H5 使用 iframe 底部有白边
用个iframe累死累活的 用 js 动态计算高度, 结果明明px都对,然后却把页面滚动条也整出来了. 查看元素盒模型也一切正常. 然后仔细观察就发现是下边多了几个像素的白色边. 然后就 百度呗 以下 ...
- scss 用法 及 es6 用法讲解
scss 用法的准备工作,下载 考拉 编译工具 且目录的名字一定不能出现中文,哪里都不能出现中文,否则就会报错 es6 用法 let 和 const let 声明变量的方式 在 {} 代码块里面才 ...
- ffplay播放YUV数据
播放器YUV系列的格式用ffplay很方便 免费的 播放NV21 ffplay -i d:/cap.yuv -pix_fmt nv21 -s 640x480 播放YUV420P ffplay -i d ...
- 在JavaScript中引用类型和值类型的区别
一.存储方式不一样 基本数据类型 变量存储的是简单的数据段,存储的是具体的值,是轻量级的数据存储方式 引用类型 引用类型的值,可以由多个值构成的对象,引用类型的变量存储的是对象引用地址.引用类型是重量 ...
- Go开发[八]goroutine和channel
进程和线程 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位. 一个进程可以创 ...