简单路径的题目,其实就是在状态后面多记了有多少个独立插头。

  分类讨论独立插头:

  1、只存在上插头或者左插头,可以选择作为独立插头。

  2、都不存在上插头和左插头,选择作为独立插头的同时要标号为新的连通块。

  换行时需特别注意,因为还有独立插头的判断,如果进行了换行操作,就会乱,特别是在不存在上插头和左插头的情况下。

  那要怎么办呢?

  我们会发现,换行后,1~m-1往后移,并把code[0]设为0,但我们在encode的时候,code[0] = 0,其实是可以忽略的操作,那么我们只需要做M-1就可以了。

  这样想来,就可以去掉shift的操作了。

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define mset(a, b) memset(a, b, sizeof(a))
const int MAXD = , HASH = , STATE = ;
int n, m, maze[MAXD][MAXD], code[MAXD], ch[MAXD];
int text[MAXD]; void Ckmax(int &AI, int BI) { if (AI < BI) AI = BI; } struct HASHMAP
{
int head[HASH], nxt[STATE], state[STATE], f[STATE], siz;
void clear() { siz = , mset(head, -); }
void push(int x, int add)
{
int pos = x%HASH, i = head[pos];
for (; i != -; i = nxt[i])
if (state[i] == x) { Ckmax(f[i], add); return ; }
state[siz] = x, f[siz] = add;
nxt[siz] = head[pos], head[pos] = siz++;
}
}hm[]; void in()
{
scanf("%d %d", &n, &m), mset(maze, );
REP(i, , n)
REP(j, , m) scanf("%d", &maze[i][j]);
} void decode(int x)
{
DWN(i, m+, ) code[i] = x&, x >>= ;
} int encode(int j)//WRONG 由于换行不能修改,要这样做
{
int ret = , cnt = , lim = (j == m) ? m- : m;
mset(ch, -), ch[] = ;
REP(i, , lim)
{
if (ch[code[i]] == -) ch[code[i]] = ++cnt;
ret <<= , ret |= ch[code[i]];
}
ret <<= , ret |= code[m+];
return ret;
} void dp_blank(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]);
int lef = code[j-], up = code[j];
if (lef && up)
{
if (lef == up) continue ;
REP(t, , m)
if (code[t] == up) code[t] = lef;
code[j-] = code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
else
{
if (lef || up)
{
int t = lef ? lef : up;
if (maze[i][j+])
{
code[j-] = , code[j] = t;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
if (maze[i+][j])
{
code[j-] = t, code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
if (code[m+]++ < )
{
code[j-] = code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
}
else
{
hm[cur^].push(encode(j), hm[cur].f[k]);
if (maze[i][j+] && maze[i+][j])//WRONG
{
code[j-] = code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
if (code[m+]++ > ) continue ;
if (maze[i][j+])
{
code[j-] = , code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
if (maze[i+][j])
{
code[j-] = , code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]+maze[i][j]);
}
}
}
}
} void dp_block(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]);
code[j-] = code[j] = ;
hm[cur^].push(encode(j), hm[cur].f[k]);
}
} void work()
{
int cur = , ans = ;
hm[].clear(), hm[].clear(), hm[].push(, );
REP(i, , n)
REP(j, , m)
{
if (maze[i][j]) dp_blank(i, j, cur);
else dp_block(i, j, cur);
hm[cur].clear(), cur ^= ;
Ckmax(ans, maze[i][j]);
}
REP(i, , hm[cur].siz-) Ckmax(ans, hm[cur].f[i]);
printf("%d\n", ans);
} int main()
{
int T;
scanf("%d", &T);
while (T --) in(), work();
return ;
}

ZOJ 3213 Beautiful Meadow 简单路径 插头DP的更多相关文章

  1. ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法

    题解 这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP. 按列转移多少与按格转移不同,但大体上还是基于连通性进行转移.每一列只有右插头是 ...

  2. zoj 2850 Beautiful Meadow

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

  3. ZOJ 3466 The Hive II (插头DP,变形)

    题意:有一个n*8的蜂房(6边形的格子),其中部分是障碍格子,其他是有蜂蜜的格子,每次必须走1个圈取走其中的蜂蜜,在每个格子只走1次,且所有蜂蜜必须取走,有多少种取法? 思路: 以前涉及的只是n*m的 ...

  4. 插头DP专题

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

  5. 插头dp的几个模板

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

  6. hdu1693:eat trees(插头dp)

    题目大意: 题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树! 给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数 题解: 这题大概是最简单的 ...

  7. P3170-[CQOI2015]标识设计【插头dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3170 题目大意 给出\(n*m\)的网格上有一些障碍,要求用三个\(L\)形(高宽随意,不能退化成线段/点)覆盖 ...

  8. 【插头dp】CDOJ1690 这是一道比CCCC简单题难的简单题

    最裸的插头dp,可参见大白书. #include<cstdio> #include<cstring> using namespace std; #define MOD 1000 ...

  9. ZOJ 3213

    /* ZOJ 3213 好吧,看过那种括号表示法后,就崩溃了,实在受不了.情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法. 最小表示法不难写: 1)首先,要承认路径上有格子不选的情况, ...

随机推荐

  1. 蓝色的PC端后台管理界面设计模板——后台

    链接:http://pan.baidu.com/s/1o82hXX4 密码:x6le

  2. APP版本号记录

    VoLTE版本: VT_BV0800V1.0.0B06 800M版本: NETARTIST_BV0800V1.0.0B01 看详细版本号:9831275#

  3. 用sar进行CPU利用率的分析

    07:40:17 PM       CPU     %user     %nice   %system   %iowait    %steal     %idle07:40:19 PM       a ...

  4. 牛奶ddw如何通过以太坊钱包实现互相打赏

    很多朋友不清楚如何转账ddw,但是万能的网友是无敌的,这两天就自己摸索的一点经验总结下今天的转账经验. 1. 提取到自己的账户 这个大家都知道如何操作,使用官方的钱包 在“日日盈app”中点击&quo ...

  5. 部署weblogic 12c的几点收获

    最近刚编写完weblogic12c的部署脚本,这里将过程中的几点收获进行记录: 1.windows下编写的脚本在linux环境下运行需要dos2unix进行格式转换 2.weblogic安装环境检测需 ...

  6. SuSE Linux Supervisor的安装与使用案例

      建议使用 root 管理员账户操作 1.安装工具 1.apache 2..Net Core(dotnet-sdk-2.0) 3.Supervisor(进程管理工具,目的是服务器一开机就启动服务器 ...

  7. leetcode 之Sum系列(七)

    第一题是Two Sum 同样是用哈希表来做,需要注意的是在查打gap是要排除本身.比如target为4,有一个值为2,gap同样为2. vector<int> twoSum(vector& ...

  8. xcode7 安装 KSImageNamed

    1.前往Xcode7的插件文件夹,路径如下: ~/Library/Developer/Xcode/Plug-ins 如果有KSImageNamed,右键删除 2.在终端直接输入命令行: default ...

  9. hdu 5920(模拟)

    Ugly Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  10. Single Image Haze Removal(图像去雾)-CVPR’09 Best Paper

    公式推导 paper闪光点 找到了一个很简洁的假设. paper不足 代码跑起来很慢.据说2010年的ECCV那篇是改进的.