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 ...
随机推荐
- ubuntu 7z解压
安装方法: sudo apt-get install p7zip 解压文件: 7z x manager.7z -r -o /home/xx 解释如下: x 代表解压缩文件,并且是按原始 ...
- 带 like 的字符串匹配查询
1.百分号通配符 '%' ,匹配任意长度的字符,甚至包括零字符 例:查询所有以 'a' 字母开头的水果,sql 语句如下 select f_id,f_name from fruits wher ...
- Spring Boot教程(十一) springboot程序构建一个docker镜像
准备工作 环境: linux环境或mac,不要用windows jdk 8 maven 3.0 docker 对docker一无所知的看docker教程. 创建一个springboot工程 引入web ...
- SQL的积累
SQL的积累学习(不常用的经常会忘记,所以以后用到的就会记在下面): --新增字段alter table t_Student add Test varchar(200)--删除字段alter tabl ...
- join的源码
long base = System.currentTimeMills(); long now = 0; if(millis < 0){ throw new IllegalArgumentE ...
- 微服务SpringCloud系列
https://my.oschina.net/hmilyylimh?tab=newest&catalogId=5703366
- jQuery.parseJSON()
https://api.jquery.com/jQuery.parseJSON/ https://api.jquery.com/category/deprecated/deprecated-3.0/ ...
- ES6数值的拓展
二进制和八进制表示法 ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示. 如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法 Number(' ...
- 搭建第一个netty程序
来自action In netty 自己修改一点点 主要依赖 <dependencies> <dependency> <groupId>io.netty</g ...
- VS调试异常代码 HRESULT:0x80070057 (E_INVALIDARG)解决方法
我目前在做的一个系统是VS2010写的的B/S架构程序, 主要技术是:C#.SQLSERVER2008.NHibernate,Python,Nhibernate 的*.hbn.xml是映射数据库的表结 ...