ZOJ 3213 Beautiful Meadow 简单路径 插头DP
简单路径的题目,其实就是在状态后面多记了有多少个独立插头。
分类讨论独立插头:
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的更多相关文章
- ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法
题解 这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP. 按列转移多少与按格转移不同,但大体上还是基于连通性进行转移.每一列只有右插头是 ...
- zoj 2850 Beautiful Meadow
Beautiful Meadow Time Limit: 2 Seconds Memory Limit: 65536 KB Tom's Meadow Tom has a meadow in ...
- ZOJ 3466 The Hive II (插头DP,变形)
题意:有一个n*8的蜂房(6边形的格子),其中部分是障碍格子,其他是有蜂蜜的格子,每次必须走1个圈取走其中的蜂蜜,在每个格子只走1次,且所有蜂蜜必须取走,有多少种取法? 思路: 以前涉及的只是n*m的 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- 插头dp的几个模板
/* ural1519 求经过全部可行点的哈密顿回路的个数 括号匹配法,转移有点复杂,可是时间空间比較小 */ #include<cstdio> #include<cstring&g ...
- hdu1693:eat trees(插头dp)
题目大意: 题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树! 给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数 题解: 这题大概是最简单的 ...
- P3170-[CQOI2015]标识设计【插头dp】
正题 题目链接:https://www.luogu.com.cn/problem/P3170 题目大意 给出\(n*m\)的网格上有一些障碍,要求用三个\(L\)形(高宽随意,不能退化成线段/点)覆盖 ...
- 【插头dp】CDOJ1690 这是一道比CCCC简单题难的简单题
最裸的插头dp,可参见大白书. #include<cstdio> #include<cstring> using namespace std; #define MOD 1000 ...
- ZOJ 3213
/* ZOJ 3213 好吧,看过那种括号表示法后,就崩溃了,实在受不了.情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法. 最小表示法不难写: 1)首先,要承认路径上有格子不选的情况, ...
随机推荐
- Linux必备工具Tmux
之前介绍了Linux的Screen命令,今天介绍一个更为强大的终端工具Tmux. Tmux 是一个用于在一个终端窗口中运行多个终端会话的工具.它基本能替代nohup以及screen,甚至比它们更为强大 ...
- long类型的数据转化为时间
long time = 111111111111111111111:SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm: ...
- webgote的例子(6)SQL注入(盲注)
SQL Injection - Blind (WS/SOAP) 本期演示的是盲注的手法.有些网站在与数据库交互的地方进行了很好的修饰,将报错的语句进行修改,即使你找到了注入点也无法下手拿数据,这个时候 ...
- linux 进程优先级 之设置实时进程 (另一种方式是设置nice值)【转】
转自:https://www.cnblogs.com/jkred369/p/6731353.html Linux内核的三种调度策略: 1,SCHED_OTHER 分时调度策略, 2,SCHED_FIF ...
- github--403错误
错误信息如下: $ git push origin master error: The requested URL returned error: while accessing https://gi ...
- PGSql
http://www.yiibai.com/postgresql/ http://www.postgresql.org/ http://blog.csdn.net/wulex/article/deta ...
- 使用 PHP 构建的 Web 应用如何避免 XSS 攻击
本文首先简单介绍开发测试人员如何对 Web 应用进行 XSS 漏洞测试,如何借助工具绕过客户端 JavaScript 校验输入恶意数据:然后针对使用 PHP 语言构建的 Web 站点,从在输出端对动态 ...
- JavaScript“并非”一切皆对象
上一篇:<函数声明和函数表达式--函数声明和函数表达式的异同> p{font-size:14px; } 写在前面 网上非常多都在说"JavaScript一切皆对象",那 ...
- day1 python简介和入门
Linux的yum依赖自带Python,为防止错误,此处更新其实就是再安装一个Python: 安装Python 1.下载安装包 https://www.python.org/downloads ...
- 实现手机端上下左右滑屏的jq原生代码和使用库·两种办法
先来一个原生的.我使用的是jq. 需要注意的地方就是被触发的元素最好不要是body,这个代码也可以修改,如果obj传进来的是body那么,$(this)必须是你的监听元素,不然会冒泡泡,整个项目就…… ...