/*
ZOJ 3213 好吧,看过那种括号表示法后,就崩溃了,实在受不了。情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法。
最小表示法不难写: 1)首先,要承认路径上有格子不选的情况,于是,在00的情况下,可扩展,也可不选。
2)不能出现环,因而不能有L=U的情况出现。
3)以下是模版代码,类同是必然。但转而求路径数的时候,应当去掉不扩展的情况,同时,在IF(L|U)的情况下,亦不必考虑当前是否为最后一个格子,
只需按写的转移即可。
4)增加独立插头时,必须在总的独立插头数小于2的情况下进行。 注意:之所以不能出现两个插头,是因为,独立插头是单向的路径,不能进了又出。限制这个条件是非常有必要的。而在此处我本以为若限制了条件就得不出
最优解,而其实,因为存在不选的状态,限制了这个条件依然是可以有最优解的。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std; const int MAXD=;
const int HASH=;
const int STATE=; int N,M;
int maze[MAXD][MAXD];
int code[MAXD];
int ch[MAXD];
int num;
int ans; struct HASHMAP
{
int head[HASH],next[STATE],size;
int state[STATE],dp[STATE];
void init()
{
size=;
memset(head,-,sizeof(head));
}
void push(int st,int ans)
{
int i,h=st%HASH;
for(i=head[h];i!=-;i=next[i])
if(state[i]==st)
{
if(dp[i]<ans)dp[i]=ans;
return;
}
state[size]=st;
dp[size]=ans;
next[size]=head[h];
head[h]=size++;
}
}hm[];
void decode(int *code,int m,int st)
{
num=st&;//??????
st>>=;
for(int i=m;i>=;i--)
{
code[i]=st&;
st>>=;
}
}
int encode(int *code,int m)
{
int cnt=;
memset(ch,-,sizeof(ch));
ch[]=;
int st=;
for(int i=;i<=m;i++)
{
if(ch[code[i]]==-)ch[code[i]]=cnt++;
code[i]=ch[code[i]];
st<<=;
st|=code[i];
}
st<<=;
st|=num;
return st;
}
void shift(int *code,int m)
{
for(int i=m;i>;i--)code[i]=code[i-];
code[]=;
}
void dpblank(int i,int j,int cur)
{
int k,left,up;
for(k=;k<hm[cur].size;k++)
{
decode(code,M,hm[cur].state[k]);
left=code[j-];
up=code[j];
if(left&&up)
{
if(left!=up)
{
code[j-]=code[j]=;
for(int t=;t<=M;t++)
if(code[t]==up)
code[t]=left;
if(j==M)shift(code,M);
hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
}
}
else if(left||up)
{
int t;
if(left)t=left;
else t=up;
if(maze[i][j+])
{
code[j-]=;
code[j]=t;
hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
}
if(maze[i+][j])
{
code[j-]=t;
code[j]=;
hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
}
if(num<) //封住一端,增加一个独立插头。
{
num++;
code[j-]=code[j]=;
hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
}
}
else
{
code[j-]=code[j]=; //讨论简单路径,只需不讨论不选的情况就可以了。
hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]);
if(maze[i][j+]&&maze[i+][j])
{
code[j-]=code[j]=;
hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
}
if(num<)
{
num++;
if(maze[i][j+])
{
code[j]=;
code[j-]=;
hm[cur^].push(encode(code,M),hm[cur].dp[k]+maze[i][j]);
}
if(maze[i+][j])
{
code[j-]=;
code[j]=;
hm[cur^].push(encode(code,j==M?M-:M),hm[cur].dp[k]+maze[i][j]);
}
}
}
}
}
void dpblock(int i,int j,int cur)
{
int k;
for(k=;k<hm[cur].size;k++)
{
decode(code,M,hm[cur].state[k]);//?????!!!
code[j-]=code[j]=;
if(j==M)shift(code,M);
hm[cur^].push(encode(code,M),hm[cur].dp[k]);
}
}
void init()
{
scanf("%d%d",&N,&M);
ans=;
memset(maze,,sizeof(maze));//???????
for(int i=;i<=N;i++)
for(int j=;j<=M;j++)
{
scanf("%d",&maze[i][j]);
if(maze[i][j]>ans)ans=maze[i][j];
}
}
void solve()
{
int i,j,cur=;
hm[cur].init();
hm[cur].push(,);
for(i=;i<=N;i++)
for(int j=;j<=M;j++)
{
hm[cur^].init();
if(maze[i][j])dpblank(i,j,cur);
else dpblock(i,j,cur);
cur^=;
}
for(i=;i<hm[cur].size;i++)
if(hm[cur].dp[i]>ans)
ans=hm[cur].dp[i];
printf("%d\n",ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
solve();
}
return ;
}

更新代码,自写的。WA了N久,感觉有几个问题要注意一下:

应当初始化图为0;

记住在增加独立插头时,任何时候要考虑是否<2

 #include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std; const int MAXD=;
const int MAXL=;
const int MAXH=;
int n,m;
int ans; int num;
int map[MAXD][MAXD];
int code[MAXD]; int pos[MAXD],stac[MAXD];
int tmp[MAXD]; struct HASHMAP{
int hash[MAXL],state[MAXH],next[MAXH];
int f[MAXH];
int size;
void init(){
size=;
memset(hash,-,sizeof(hash));
}
void push(int st,int anst) {
int h=st%MAXL;
for(int i=hash[h];i!=-;i=next[i]){
if(state[i]==st){
if(f[i]<anst){
f[i]=anst;
}
return ;
}
}
state[size]=st;
f[size]=anst;
next[size]=hash[h];
hash[h]=size++;
}
}hm[]; void decode(int st){
for(int i=m;i>=;i--){
int t=st&;
code[i]=t;
st=st>>;
}
} int fd_r(int j){
int top=-;
for(int i=;i<=m;i++){
if(code[i]==) continue;
else if(code[i]==){
++top;
pos[top]=i; stac[top]=code[i];
}
else if(code[i]==){
if(pos[top]==j) return i;
else top--;
}
}
}
int fd_l(int j){
int top=-;
for(int i=;i<=m;i++){
if(code[i]==) continue;
else if(code[i]==){
++top;
pos[top]=i; stac[top]=code[i];
}
else if(code[i]==){
if(i==j) return pos[top];
else top--;
}
}
} void dpblank(int i,int j,int cur){
int em;int tmpst; int ls,us,tts;
for(int e=;e<hm[cur].size;e++){
int st=hm[cur].state[e];
num=st&;
st>>=;
decode(st);
int left=code[j-],up=code[j];
ls=(m-j+)*; us=(m-j)*;
if(!left&&!up){
tmpst=(st^(left<<ls))^(up<<us);
if(j==m) tmpst=tmpst>>;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]);
if(map[i+][j]>&&map[i][j+]>){
tmpst=(st^(left<<ls))^(<<ls);
tmpst=(tmpst^(up<<us))^(<<us);
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
if(num<){
num++;
if(map[i][j+]>){
tmpst=(st^(left<<ls));
tmpst=(tmpst^(up<<us))^(<<us);
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
if(map[i+][j]>){
tmpst=(st^(left<<ls))^(<<ls);
tmpst=(tmpst^(up<<us));
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
}
}
else if(left&&up){
if(left==&&up==){
int tt=fd_r(j);
tts=(m-tt)*;
tmpst=(st^(code[tt]<<tts))^(<<tts);
tmpst=(tmpst^(left<<ls));
tmpst=(tmpst^(up<<us));
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
else if(left==&&up==){
int tt=fd_l(j-);
tts=(m-tt)*;
tmpst=(st^(code[tt]<<tts))^(<<tts);
tmpst=(tmpst^(left<<ls));
tmpst=(tmpst^(up<<us));
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
else if(left==&&up==){
tmpst=(st^(left<<ls));
tmpst=(tmpst^(up<<us));
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
else if(left==&&up==){
tmpst=(st^(left<<ls));
tmpst=(tmpst^(up<<us));
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
else if(left==&&up!=){
int tt;
if(up==) tt=fd_r(j);
else tt=fd_l(j);
tts=(m-tt)*;
tmpst=st^(left<<ls);
tmpst=tmpst^(up<<us);
tmpst=(tmpst^(code[tt]<<tts))^(<<tts);
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
else if(left!=&&up==){
int tt;
if(left==) tt=fd_r(j-);
else tt=fd_l(j-);
tts=(m-tt)*;
tmpst=st^(left<<ls);
tmpst=tmpst^(up<<us);
tmpst=(tmpst^(code[tt]<<tts))^(<<tts);
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
}
else{
int tt,cott;
if(left) tt=left;
else tt=up;
if(map[i][j+]>){
tmpst=st^(up<<us)^(tt<<us);
tmpst=tmpst^(left<<ls);
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
if(map[i+][j]>){
tmpst=st^(left<<ls)^(tt<<ls);
tmpst=tmpst^(up<<us);
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
if(tt==&&num<){ //忘了限制条件<2,WA了N久。
tmpst=st^(left<<ls)^(up<<us);
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=(num+);
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
if(left!=&&up!=&&num<){
int sp=(tt==left? j-: j);
tts=(m-sp)*;
if(tt==) cott=fd_r(sp);
else cott=fd_l(sp);
tmpst=st^(code[sp]<<tts)^(code[cott]<<((m-cott)*))^(<<((m-cott)*));
if(j==m) tmpst>>=;
num++;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[e]+map[i][j]);
}
}
}
} void dpblock(int i,int j,int cur){
int em; int tmpst;
for(int k=;k<hm[cur].size;k++){
int st=hm[cur].state[k];
num=st&;
st>>=;
decode(st);
tmpst=st^(code[j]<<((m-j)*))^(code[j-]<<((m-j+)*));
if(j==m) tmpst>>=;
tmpst<<=;
tmpst|=num;
hm[cur^].push(tmpst,hm[cur].f[k]);
}
} void solve(){
int cur=,i;
hm[cur].init();
hm[cur].push(,);
for( i=;i<=n;i++){
for(int j=;j<=m;j++){
hm[cur^].init();
if(map[i][j]>) dpblank(i,j,cur);
else dpblock(i,j,cur);
cur=cur^;
}
}
for( i=;i<hm[cur].size;i++)
if(hm[cur].f[i]>ans) ans=hm[cur].f[i];
printf("%d\n",ans);
} int main(){
int T; int i,j;
scanf("%d",&T);
while(T--){
ans=;
scanf("%d%d",&n,&m);
memset(map,,sizeof(map));
for(i=;i<=n;i++){
for(j=;j<=m;j++){
scanf("%d",&map[i][j]);
if(map[i][j]>ans) ans=map[i][j];
}
}
solve();
}
return ;
}

ZOJ 3213的更多相关文章

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

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

  2. 插头DP专题

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

  3. 插头dp的几个模板

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

  4. ZOJ People Counting

    第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ  3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...

  5. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  6. ZOJ Problem Set - 1394 Polar Explorer

    这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...

  7. ZOJ Problem Set - 1392 The Hardest Problem Ever

    放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...

  8. ZOJ Problem Set - 1049 I Think I Need a Houseboat

    这道题目说白了是一道平面几何的数学问题,重在理解题目的意思: 题目说,弗雷德想买地盖房养老,但是土地每年会被密西西比河淹掉一部分,而且经调查是以半圆形的方式淹没的,每年淹没50平方英里,以初始水岸线为 ...

  9. ZOJ Problem Set - 1006 Do the Untwist

    今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...

随机推荐

  1. 推荐给Web前端开发人员的一些书籍(从基础到架构阶段)

    有很多人问我说作为一个前端开发人员都需要看一些什么书籍,尤其是刚入门的新手,今天我整理了一下推荐给大家,大佬绕过. HTML+CSS+JavaScript 网页设计 从入门到精通 作为一个前端新手,强 ...

  2. 基于ASP.Net Core开发一套通用后台框架记录-(项目的搭建)

    写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...

  3. 【转】linux下vi命令大全

    转自:http://www.cnblogs.com/88999660/articles/1581524.html 进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi ...

  4. 在 kafka 的 broke 和 client 之间加入 SSL 双向认证

    在 kafka 的 broke 和 client 之间加入 SSL 双向认证https://blog.csdn.net/hohoo1990/article/details/79110031 kafka ...

  5. struts2.1.6存在中文乱码的bug

    如题,后续版本中已解决:可以通过添加filter的方式解决.

  6. SV creation order

    SystemVerilog Instance Worlds When generating an UVM testbench and in particular the DUT - testbench ...

  7. jQuery——stop

    为什么要停止动画? 对同一个元素,如果拥有一个以上的动画对其加以作用,那么后面的动画会被放入一个动画队列中.动画队列的动画是在其上一个动画完成以后才会执行. 控制两个参数四种情况 1.第一个参数表示后 ...

  8. 仿iphone动态萤火虫锁屏应用安卓源码

    该源码是仿iphone动态萤火虫锁屏应用源码,源码SkyLock,这也是最近弄了一款锁屏,苦于市场百般阻拦与锁屏应用数量实在太多,于是将它拿出来开源:废话不多说,希望大家能够希望,更多说明请看下面的吧 ...

  9. C语言保留字

    数值变量相关: int float double char long short unsigned signed 储存说明符 const 用于声明常量 static用于限制变量/函数的作用范围等等 e ...

  10. 【Caffe】Ubuntu16.04上配置安装caffe(Only CPU)

    一.首先看看自己的系统,Ubuntu16.04,cpu,没有Nvidia,没有opencv 二.安装依赖包 安装protobuf,leveldb,snappy,OpenCV,hdf5, protobu ...