插头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. iOS 判断数组array中是否包含元素a,取出a在array中的下标+数组方法详解

    目前找到来4个解决办法,第三个尤为简单方便 NSArray * arr = @["]; //是否包含 "]) { NSInteger index = [arr indexOfObj ...

  2. iOS中self与_的区别

    同时我们发现在我们访问我们声明的变量时,会有self. 和 以"_"开头的访问方式,那么这两种方式到底有什么样的区别呢? 我们来一起看一下: @property (retain, ...

  3. ABP .Net Core Entity Framework迁移使用MySql数据库

    一.迁移说明 ABP模板项目Entity Framework Core默认使用的是Sql Server,也很容易将数据库迁移到MySQL,步骤如下. 二.迁移MySQL步骤 1. 下载项目 请到 ht ...

  4. iView的使用【CDN向】

    直接粗暴地上html代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  5. JavaScript的DOM编程--08--复习

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  6. windows的ReactNative挖坑一分钟爬坑一小时

    其实开发并不需要Android Studio来开发,因为命令行都是要自己手打的,所以就开始了我的挖坑爬坑之旅 首先安装React Native要用到的git.nodejs等等这里不讲了,主要讲在手机上 ...

  7. 析构函数(C#)

    析构函数又称终结器,用于析构类的实例. 定义 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数.析构函数往往用来做&quo ...

  8. JS中金额转换以及格式化

    abs = function(val){ //金额转换 分->元 保留2位小数 并每隔3位用逗号分开 1,234.56 var str = (val/100).toFixed(2) + ''; ...

  9. Android Ptrace Inject

    之前介绍了Android平台上3种常见的hook方法,而hook的前提是进程注入,通过进程注入我们可以将模块或代码注入到目标进程中以便对其空间内的数据进行操作,本篇文章介绍基于ptrace函数的注入技 ...

  10. MySQL 基础命令

    的说法啊打发 第1章 SQL语句 mysql版本:针对mysql-5.6.36 版本 (5.7会有一些变动) 1.1 常用命令 # 查看数据库 mysql> show databases; sh ...