插头DP。。。网格图,有障碍,格子上有权值,求总权值最大的简单路径。

  因为路径的起始点不确定。。所以多开一维表示当前已经有多少个独立插头。。

  只要不合并相同的联通块,并且已经用了2个独立插头,那就是一条简单路径了。。。

  需要特判路径上只有一个点的情况。

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int modd=,maxzt=;
struct zs1{
struct zs{
int pre;ll too;
}e[maxzt];int tot,last[modd];
int f[maxzt];ll zt[maxzt];
inline int get(ll v){
int i,x=v%modd;
for(i=last[x];i&&e[i].too!=v;i=e[i].pre);
if(i)return i;
e[++tot].too=v,e[tot].pre=last[x],last[x]=tot,
f[tot]=,zt[tot]=v;
return tot;
}
}hm[][]; int i,j,k,n,m;
bool can[][];int val[][];
int mp[],id[];bool u[]; inline void clr(bool now,int num){
memset(hm[now][num].last,,modd<<);
hm[now][num].tot=;
}
inline void upd(int &a,int b){if(b>a)a=b;}
inline void decode(ll x){
for(int i=m;i>=;i--)mp[i]=x&,x>>=;
}
inline ll encode(){
int i,tt=;ll x=;
memset(u,,);
for(i=;i<=m;mp[i]=id[mp[i]],x=x<<|mp[i],i++)
if(!u[mp[i]]&&mp[i]>)u[mp[i]]=,id[mp[i]]=++tt;
return x;
}
inline void dp_blank(int x,int y,bool pre){
int i,left,up,f;ll zt;bool now=pre^;
for(int num=;num<=;num++){
// printf(" %d,%d %d\n",x,y,num);
clr(now,num);
for(i=;i<=hm[pre][num].tot;i++){
zt=hm[pre][num].zt[i],f=hm[pre][num].f[i];
if(y==)zt>>=;
decode(zt);
// for(int j=0;j<=m;j++)printf(" %d",mp[j]);printf(" %d zt:%lld\n",f,zt);
left=mp[y-],up=mp[y];
if(left&&up&&left!=up){
mp[y-]=mp[y]=;
for(int j=;j<=m;j++)if(mp[j]==up){mp[j]=left;break;}
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
}
if(!left&&!up){
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f );
if(can[x+][y]&&can[x][y+])
mp[y-]=mp[y]=,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
}
if((!left)^(!up)){
int j=left|up;
if(can[x+][y])
mp[y-]=j,mp[y]=,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
if(can[x][y+])
mp[y-]=,mp[y]=j,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
}
}
if(num>)
for(i=;i<=hm[pre][num-].tot;i++){
zt=hm[pre][num-].zt[i],f=hm[pre][num-].f[i];
if(y==)zt>>=;
decode(zt);
// for(int j=0;j<=m;j++)printf(" %d",mp[j]);printf(" (dl) %d zt:%lld\n",f,zt);
left=mp[y-],up=mp[y];
if(!left&&!up){
if(can[x+][y])
mp[y-]=,mp[y]=,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
if(can[x][y+])
mp[y-]=,mp[y]=,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );//,printf(" %lld %d\n",encode(),y);
}
if((!left)^(!up))
mp[y-]=mp[y]=,
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
}
}
}
inline void dp_bar(int x,int y,bool pre){
int i,left,up,f;ll zt;bool now=pre^;
for(int num=;num<=;num++){
clr(now,num);
for(i=;i<=hm[pre][num].tot;i++){
zt=hm[pre][num].zt[i],f=hm[pre][num].f[i];
if(y==)zt>>=;
decode(zt),
left=mp[y-],up=mp[y];
if(!left&&!up)
upd( hm[now][num].f[ hm[now][num].get(encode()) ] , f+val[x][y] );
}
}
} int ra;char rx;
inline int read(){
rx=getchar(),ra=;
while(rx<''||rx>'')rx=getchar();
while(rx>=''&&rx<='')ra*=,ra+=rx-,rx=getchar();return ra;
}
int main(){
for(int T=read();T;T--){
n=read(),m=read();
memset(can,,sizeof(can));
int ans=;
for(i=;i<=n;i++)for(j=;j<=m;j++)val[i][j]=read(),can[i][j]=val[i][j]!=,ans=max(ans,val[i][j]);
bool pre=,now=;
clr(pre,),clr(pre,),clr(pre,);
hm[pre][].f[ hm[pre][].get() ]=;
for(i=;i<=n;i++)for(j=;j<=m;j++,swap(pre,now))
if(can[i][j])dp_blank(i,j,pre);else dp_bar(i,j,pre);
for(i=;i<=hm[pre][].tot;i++)
upd(ans,hm[pre][].f[i]);
printf("%d\n",ans);
}
return ;
}

[ZOJ3213] Beautiful Meadow的更多相关文章

  1. zoj 2850 Beautiful Meadow

    Beautiful Meadow Time Limit: 2 Seconds      Memory Limit: 65536 KB Tom's Meadow Tom has a meadow in ...

  2. ZOJ 3213 Beautiful Meadow 简单路径 插头DP

    简单路径的题目,其实就是在状态后面多记了有多少个独立插头. 分类讨论独立插头: 1.只存在上插头或者左插头,可以选择作为独立插头. 2.都不存在上插头和左插头,选择作为独立插头的同时要标号为新的连通块 ...

  3. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  4. 杭电ACM分类

    杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...

  5. 插头dp的几个模板

    /* ural1519 求经过全部可行点的哈密顿回路的个数 括号匹配法,转移有点复杂,可是时间空间比較小 */ #include<cstdio> #include<cstring&g ...

  6. DP:0

    小故事: A * "1+1+1+1+1+1+1+1 =?" * A : "上面等式的值是多少" B : *计算* "8!" A *在上面等式 ...

  7. 转载:hdu 题目分类 (侵删)

    转载:from http://blog.csdn.net/qq_28236309/article/details/47818349 基础题:1000.1001.1004.1005.1008.1012. ...

  8. ZOJ 2850和ZOJ 1414

    下午上数据结构,结果竟然没有新题.T T果断上OJ来水一发 ZOJ 2850   Beautiful Meadow 传送门http://acm.zju.edu.cn/onlinejudge/showP ...

  9. 使用Beautiful Soup编写一个爬虫 系列随笔汇总

    这几篇博文只是为了记录学习Beautiful Soup的过程,不仅方便自己以后查看,也许能帮到同样在学习这个技术的朋友.通过学习Beautiful Soup基础知识 完成了一个简单的爬虫服务:从all ...

随机推荐

  1. JavaWeb之Java Servlet完全教程(转)

    Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求. Servle ...

  2. HTML基础教程-段落

    HTML 段落 段落是通过 <p> 标签定义的. <p>This is a paragraph</p> <p>This is another parag ...

  3. jQuery模块化开发

    //定义了命名空间. var Itcast = {}; //定义第二级别的 命名空间. var Itcast.Model = {}; var Itcast.Model.UIJs = (function ...

  4. [编织消息框架][netty源码分析]12 ByteBuf 实现类UnpooledDirectByteBuf职责与实现

    public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { private final ByteBufAl ...

  5. ThinkPHP使用阿里云通信短信服务

    一.下载SDK 目前给出的SDK版本有JAVA.PHP.Python三个版本,我们使用PHP版本 二.文档结构 将下载的PHP-SDK解压,放入tp框架的Library目录下 发送短信主要使用api_ ...

  6. 神经网络 误差逆传播算法推导 BP算法

      误差逆传播算法是迄今最成功的神经网络学习算法,现实任务中使用神经网络时,大多使用BP算法进行训练.   给定训练集\(D={(x_1,y_1),(x_2,y_2),......(x_m,y_m)} ...

  7. Python 接口自动化(预)

    1. HTTP协议:HTTP是接口测试的基础: 2. Fiddler工具:Fiddler所有界面布局及主要布局

  8. Oracle (11g) 修改默认的用户名及密码

    Oracle11g的云盘连接 Q1:安装完成Oracle数据后如何登录? A1:打开cmd窗口,输入sqlplus / as sysdba 后回车,以超级管理员身份登录,成功后如图所示(可以看到是or ...

  9. Linux 笔记 #02# Installing MySQL & Installing the Default JRE/JDK

    Environment: debian 8 Installing MySQL Reference material: https://linode.com/docs/databases/mysql/h ...

  10. opencv提供的带参数例程

    body { font-family: @微软雅黑; font-size: 8pt; line-height: 1.5 } html,body { color: inherit; background ...