【BZOJ2310】ParkII 插头DP
【BZOJ2310】ParkII
Description
Hnoi2007-Day1有一道题目 Park:给你一个 m * n 的矩阵,每个矩阵内有个权值V(i,j) (可能为负数),要求找一条回路,使得每个点最多经过一次,并且经过的点权值之和最大,想必大家印象深刻吧.
无聊的小 C 同学把这个问题稍微改了一下:要求找一条路径,使得每个点最多经过一次,并且点权值之和最大,如果你跟小 C 一样无聊,就麻烦做一下这个题目吧.
Input
第一行 m, n,接下来 m行每行 n 个数即.
V( i,j)
Output
一个整数表示路径的最大权值之和.
Sample Input
1 -2 1
1 1 1
Sample Output
【数据范围】
30%的数据,n≤6.
100%的数据,m<=100,n ≤ ≤8.
注意:路径上有可能只有一个点.
题解:神奇游乐园的加强版,加入了独立插头,方法是用4进制数表示状态,0-无插头,1-左括号,2-右括号,3-独立插头。然后就进行4*4=16种情况的讨论吧!
注意以下几点即可:
一个独立插头可以与一个括号匹配使得另一个括号变成独立插头;新建独立插头的条件是已有独立插头数<2;一个原本匹配的插头可以自我了断,然后与它匹配的那个插头就变成独立插头了;当两个独立插头匹配时更新答案。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m,tot,k,ans;
int hs[270000],ref[8320],dp[2][8320],cnt[8320];
inline void upd(int x,int y)
{
if(dp[k][hs[x]]<y) dp[k][hs[x]]=y;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd(),ans=0xc0c0c0c0;
int tmp,u,i,j,v,x,y,tag,p,q,S,T;
memset(dp[0],0xc0,sizeof(dp[0]));
for(S=0;S<(1<<(m+m+2));S++)
{
for(v=tmp=0,u=0;u<=(m<<1)&&v>=0&&tmp<=2;u+=2) x=(S>>u)&3,v+=(x==1)-(x==2),tmp+=(x==3);
if(tmp<=2&&v==0) ref[++tot]=S,cnt[tot]=tmp,hs[S]=tot;
}
dp[0][1]=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
v=rd(),ans=max(ans,v),k^=1;
memset(dp[k],0xc0,sizeof(dp[k]));
dp[k][1]=0;
for(S=1;S<=tot;S++)
{
y=j<<1,x=y-2,p=(ref[S]>>x)&3,q=(ref[S]>>y)&3,tag=dp[k^1][S]+v,T=ref[S]^(p<<x)^(q<<y);
if(!p&&!q)
{
if(cnt[S]<2)
{
if(i!=n) upd(T|(3<<x),tag);
if(j!=m) upd(T|(3<<y),tag);
}
if(i!=n&&j!=m) upd(T|(1<<x)|(2<<y),tag);
upd(T,tag-v);
}
if((!p&&q==1)||(!q&&p==1))
{
if(i!=n) upd(T|(1<<x),tag);
if(j!=m) upd(T|(1<<y),tag);
if(cnt[S]<2)
{
for(u=y+2,tmp=0;u<=(m<<1)&&tmp>=0;tmp+=((T>>u)&1)-((T>>(u+1))&1),u+=2);
u-=2;
upd(T|(1<<u),tag);
}
}
if((!p&&q==2)||(!q&&p==2))
{
if(i!=n) upd(T|(2<<x),tag);
if(j!=m) upd(T|(2<<y),tag);
if(cnt[S]<2)
{
for(u=x-2,tmp=0;u>=0&&tmp>=0;tmp+=((T>>(u+1))&1)-((T>>u)&1),u-=2);
u+=2;
upd(T|(2<<u),tag);
}
}
if((!p&&q==3)||(!q&&p==3))
{
if(i!=n) upd(T|(3<<x),tag);
if(j!=m) upd(T|(3<<y),tag);
if(!T&&ans<tag) ans=tag;
}
if(p==3&&q==3&&!T&&ans<tag) ans=tag;
if(p==2&&q==1) upd(T,tag);
if((p==1&&q==3)||(p==3&&q==1))
{
for(u=y+2,tmp=0;u<=(m<<1)&&tmp>=0;tmp+=((T>>u)&1)-((T>>(u+1))&1),u+=2);
u-=2;
upd(T|(1<<u),tag);
}
if((p==2&&q==3)||(p==3&&q==2))
{
for(u=x-2,tmp=0;u>=0&&tmp>=0;tmp+=((T>>(u+1))&1)-((T>>u)&1),u-=2);
u+=2;
upd(T|(2<<u),tag);
}
if(p==1&&q==1)
{
for(u=y+2,tmp=0;u<=(m<<1)&&tmp>=0;tmp+=((T>>u)&1)-((T>>(u+1))&1),u+=2);
u-=2;
upd(T^(3<<u),tag);
}
if(p==2&&q==2)
{
for(u=x-2,tmp=0;u>=0&&tmp>=0;tmp+=((T>>(u+1))&1)-((T>>u)&1),u-=2);
u+=2;
upd(T^(3<<u),tag);
}
}
}
for(S=tot;S>=1;S--)
{
if(!(ref[S]&3)) dp[k][S]=dp[k][hs[ref[S]>>2]];
else dp[k][S]=0xc0c0c0c0;
}
}
printf("%d",ans);
return 0;
}//2 3 1 -2 1 1 1 1
【BZOJ2310】ParkII 插头DP的更多相关文章
- 【BZOJ】2310: ParkII 插头DP
[题意]给定m*n的整数矩阵,求经过所有点至多一次路径的最大数值和.n<=8,m<=100. [算法]插头DP [题解]最小表示法确实十分通用,处理简单路径问题只需要状态多加一位表示独立插 ...
- [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...
- 插头dp初探
问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...
- 「总结」插头$dp$
集中做完了插头$dp$ 写一下题解. 一开始学的时候还是挺蒙的. 不过后来站在轮廓线$dp$的角度上来看就简单多了. 其实就是一种联通性$dp$,只不过情况比较多而已了. 本来转移方式有两种.逐行和逐 ...
- 插头dp
插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- HDU 4949 Light(插头dp、位运算)
比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
随机推荐
- Thinkphp5笔记二:创建模块
系统:window 7 64位 Thinkphp版本:5.0.5 环境:wampserver集成 我的项目是部署在本地www/thinkphp 目录下.在做之前,先要考虑清楚,你需要几个模块来完成你 ...
- VIM技巧:选择文本块
在正常模式下(按ESC进入)按键v进入可视化模式,然后按键盘左右键或h,l键即可实现文本的选择.其它相关命令:v:按字符选择.经常使用的模式,所以亲自尝试一下它. V:按行选择.这在你想拷贝或者移动很 ...
- input checkbox复选框点击获取当前选中状态jquery
function checkAll(id) { //用is判断 // let checkStatus=$(id).is(':checked'); // console.log(checkStatus) ...
- xml文件加密上传和sftp下载解密基本思路
AES对称加密效率高,对大文件加密适合.RSA非对称加密效率低,更安全,对小文件加密适合. 整理 11:12 2016/8/4 加密:1.xml xml.md5摘要 2.(xml)aes加密 (xml ...
- 图像中的artifacts
artifacts 瑕疵 伪影(Artifacts) 伪影(Artifacts)-CT-基础术语 - 影像园 http://www.xctmr.com/baike/ct/c34b5413e305b45 ...
- QT运行出错:QObject::connect: Parentheses expected以及QObject::connect: No such slot ***
我在QGraphicsScene子类中添加了item的弹出菜单,并连接Action到槽函数,结果槽函数不起作用,输出:QObject::connect: No such slot *** C++ C ...
- 从Python学习中得到的一点启发 - Java逆向索引ArrayList
看了几天Python,感觉记忆力不行了,很多东西记不住了.但是终归是得到了一点知识:重写一个ArrayList,允许从负值的索引得到指定的项.然后写一个得到斐波拉契数组的方法,这种方法要比递归调用的方 ...
- Dubbo调用链(version:2.5.3)
Consumer 调用 Provider的过程: (CONSUMER)Dubbo服务调用处 --> 调用RPC代理 --> InvokerInvocationHandler#invoke( ...
- [转]Struts2多个文件上传
转载至:http://blog.csdn.net/hanxiaoshuang123/article/details/7342091 Struts2多个文件上传多个文件上传分为List集合和数组,下面我 ...
- RF中采用python方法获取当月1号、上月1号、下月1号、当前日期N天后日期、当前日期N天前日期、指定月份总天数、上个月份、下个月份、当月最后1天日期、上个月最后1天日期、下个月最后1天日期
${TodayDate} evaluate datetime.date.today().strftime('%Y%m%d') datetime ${CurrentMonthFirstDay} eval ...