插头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. Error Running Git Empty git --version output:IDEA关联GitHub时出现这个错误

    刚刚学习使用idea中,想要把自己的项目上传到github,遇到这样一个问题,先记录下来,到时候解决了在把方法贴出来. ---------------------------------------- ...

  2. k-近邻算法实例

    1. 简单例子 步骤 1.1 计算已知点和被求点的距离 1.2 按距离递增排序 1.3 求出距离最近的前k个点的类别最大值作为目标分类 from numpy import * import opera ...

  3. geoserver集成以及部署arcgis server瓦片数据

    关注重点: 一般来说,geoserver是不支持arcgis server格式瓦片数据部署的,至少我本机的geoserver版本(2.8.5)以及之前的版本并没有集成进来,不知道目前官网的最新版是否支 ...

  4. csdn博客被删除联系客服恢复

    前几天写了篇"如何使用shadowsocksFQ",居然被删除,我很郁闷,客服给我的回答是"影响了客户体验,网安查的严,不能带有FQ的信息出现" 我一直很郁闷, ...

  5. 房上的猫:类和对象>万物皆对象

    众所周知:java是一门面向对象的编程语言 本章将介绍基础的类和对象 一.对象 对象是用来描述客观事物的一个实体,由一组属性和方法构成二.封装 封装就是把一个事物包装起来,并尽可能隐藏内部细节三.类  ...

  6. MySQL一对一:一对多:多对多: 实例!!!!

    学生表和课程表可以多对多 一个学生可以学多门课程 一门课程可以有多个学生: 多对多 *** 一个学生对应一个班级 一个班级对应多个学生: 一对多 *** 一个老师对应多个学生 多个学生对应一个老师:一 ...

  7. Java中对List<E>按E的属性排序的简单方法

    这是LeetCode上的题目56. Merge Intervals中需要用到的, 简单来说,定义了E为 /** * Definition for an interval. * public class ...

  8. vue2.0 资源文件assets和static的区别

    资源文件处理 在我们的项目结构里,有两个资源文件的路径,分别是:src/assets 和 static/.那这两个到底有什么区别呢? Webpacked 资源 为了回答这个问题,我们首先需要理解web ...

  9. yield next和yield* next的区别

    yield next和yield* next之间到底有什么区别?为什么需要yield* next?经常会有人提出这个问题.虽然我们在代码中会尽量避免使用yield* next以减少新用户的疑惑,但还是 ...

  10. C#Winform使用mysql作为本地数据库

    MYSQL是老牌关系型数据库,在受够了sqlite,mslocaldb,sqlce等本地数据库之后,发现了mysql5.6的一些版本也可以绿色安装,编程实现从资源文件里面解压到目标机器上,并配置好成为 ...