/*
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. linux安装/卸载mysql

    其实安装mysql差不多有10次了吧, 但是每次都有坑,各种百度,太麻烦了,所以这次把坑给记录下来,下次直接用. 1. 去官网下载mysql.这里可以使用wget下载.先去官方网站,找到mysql5. ...

  2. Hadoop Hive概念学习系列之hive里的优化和高级功能(十四)

    在一些特定的业务场景下,使用hive默认的配置对数据进行分析,虽然默认的配置能够实现业务需求,但是分析效率可能会很低. Hive有针对性地对不同的查询进行了优化.在Hive里可以通过修改配置的方式进行 ...

  3. java中使用String的replace方法替换html模板保存文件

    在我们的D盘下有这样一个html模板,现在我们要做的就是解析news.template文件,从数据库中提取数据将数据添加到指定的模板位置上 <head> <title>{tit ...

  4. Java中的overload(方法的覆写)

    方法覆写(overload)与方法的重载非常相似,它在 Java的继承中也有很重要的应用. 写程序可能会碰到下面的情况,在父类中已经实现的方法可能不够精确,不能满足子类 的需求.例如在前面的 Anim ...

  5. Android彻底组件化demo发布

    今年6月份开始,我开始负责对"得到app"的android代码进行组件化拆分,在动手之前我查阅了很多组件化或者模块化的文章,虽然有一些收获,但是很少有文章能够给出一个整体且有效的方 ...

  6. 【sqli-labs】 less52 GET -Blind based -Order By Clause -numeric -Stacked injection(GET型基于盲注的整型Order By从句堆叠注入)

    出错被关闭了 http://192.168.136.128/sqli-labs-master/Less-52/?sort=1' http://192.168.136.128/sqli-labs-mas ...

  7. (转) Arcgis4js实现链家找房的效果

    http://blog.csdn.net/gisshixisheng/article/details/71009901 概述 买房的各位亲们不知是否留意过链家的"地图找房",这样的 ...

  8. (转) Hibernate框架基础——操纵持久化对象的方法(Session中)

    http://blog.csdn.net/yerenyuan_pku/article/details/52761021 上一篇文章中我们学习了Hibernate中java对象的状态以及对象的状态之间如 ...

  9. vsftpd:500OOPS:vsftpd:refusingtorunwithwritablerootinsidechroot()错误的解决方法

    当我们限定了用户不能跳出其主目录之后,使用该用户登录FTP时往往会遇到这个错误: 500 OOPS: vsftpd: refusing to run with writable root inside ...

  10. python socket 接口

    一.简介 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求.socket起 ...