您的位置:首页 > 其它

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

2018-03-23 12:05 246 查看
题面:

传送门

给定一个四联通棋盘图,每个格子有权值,求一条总权值最大的回路

思路:

插头dp基础教程

棋盘?

回路?

n,m<=10?

当然是插头dp啦~\(≧▽≦)/~

然后发现这道题并不是哈密顿回路了......需要考虑一下终止条件的不同,对比URAL1519

诚然,回路问题中依然可以用括号表示法来压缩状态,但是此时形成回路、统计答案的就不仅仅在最后一个非障碍格子才可以,而是任何时候,只要状态中只剩下一对左右插头满足条件(看不懂这里的可以去上面那道题看看)

同时请注意,这道题统计的是最值、不是和值

同时请注意,这题可能会爆longlong......我丧病地开了__int128,避免了高精度的地狱

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define hash deep_dark_fantasy
#define inf 1e9
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,x[150][150],cur,pre,ex,ey;
int st[2][300010];ll ans[2][300010],re;
int tot[2],bit[20],state[300010],st_tot,hash=300000;
struct edge{
int to,next;
}a[300010];
void insert(int sta,ll val){
int p=sta%hash,i;
for(i=state[p];i;i=a[i].next){
if(st[cur][a[i].to]==sta){
ans[cur][a[i].to]=max(ans[cur][a[i].to],val);return;
}
}
tot[cur]++;
a[++st_tot].to=tot[cur];
a[st_tot].next=state[p];
state[p]=st_tot;st[cur][tot[cur]]=sta;ans[cur][tot[cur]]=val;
}
void dp(){
int i,j,k,l,now,down,right;ll val;re=-inf;
cur=0;tot[cur]=1;ans[cur][1]=0;st[cur][1]=0;
for(i=1;i<=n;i++){
for(j=1;j<=tot[cur];j++) st[cur][j]<<=2;
for(j=1;j<=m;j++){
pre=cur;cur^=1;tot[cur]=0;st_tot=0;memset(state,0,sizeof(state));
for(k=1;k<=tot[pre];k++){
now=st[pre][k];val=ans[pre][k];
right=(now>>bit[j-1])%4;down=(now>>bit[j])%4;
if(!down&&!right){
insert(now,val);
if(j!=m)
insert(now+(1<<bit[j-1])+((1<<bit[j])<<1),val+x[i][j]);
}
if(down&&!right){
insert(now-down*(1<<bit[j])+down*(1<<bit[j-1]),val+x[i][j]);
if(j!=m)insert(now,val+x[i][j]);
}
if(right&&!down){
insert(now,val+x[i][j]);
if(j!=m)
insert(now+right*(1<<bit[j])-right*(1<<bit[j-1]),val+x[i][j]);
}
if(right==1&&down==1){
int cnt=1;
for(l=j+1;l<=m;l++){
if((now>>bit[l])%4==1) cnt++;
if((now>>bit[l])%4==2) cnt--;
if(!cnt){
insert(now-(1<<bit[l])-(1<<bit[j])-(1<<bit[j-1]),val+x[i][j]);
break;
}
}
}
if(right==2&&down==2){
int cnt=1;
for(l=j-2;l>=0;l--){
if((now>>bit[l])%4==1) cnt--;
if((now>>bit[l])%4==2) cnt++;
if(!cnt){
insert(now+(1<<bit[l])-((1<<bit[j])<<1)-((1<<bit[j-1])<<1),val+x[i][j]);
break;
}
}
}
if(right==2&&down==1){
insert(now-((1<<bit[j-1])<<1)-(1<<bit[j]),val+x[i][j]);
}
if(right==1&&down==2){
if((now==(1<<bit[j-1])+((1<<bit[j])<<1))&&(val+x[i][j]>re)){
re=val+x[i][j];
}
}
}
}
}
}
int main(){
int i,j;
n=read();m=read();
for(i=1;i<=10;i++) bit[i]=(i<<1);
for(i=1;i<=n;i++) for(j=1;j<=m;j++) x[i][j]=read();
dp();
printf("%lld",re);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: