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)首先,要承认路径上有格子不选的情况, ...
随机推荐
- java中的matches -> 完全匹配
matches是完全匹配.跟matcher不一样, matcher像perl正则, 能匹配到符合的都会返回true, 而这个matches要完全一模一样才行. import java.util.reg ...
- php审计学习:xdcms2.0.8注入
注入点Fields: 注册页面会引用如下方法: $fields 变量是从 $fields=$_POST['fields']; 这里获取, 在代码里没有过滤. 打印 fields 数据查看: 从代码上看 ...
- curl: (6) Couldn’t resolve host ‘www.ttlsa.com’【转】
上周, 部分站点出现Couldn't resolve host.....问题, 导致公司所有走api的程序都无法正常使用(系统redhat 6.3的都出现问题, redhat 5一切OK). 最后解 ...
- localhost或127.0.0.1或192.168.1.*被转到129129.com上的问题
系统启动里会有个httpd的apache程序在运行,自启禁用掉后.windows下有个apache文件夹,干掉就可以. 个别GHOST XP程序里面会装这种流氓程序.
- 84.Largest Rectangle in histogram---stack
题目链接:https://leetcode.com/problems/largest-rectangle-in-histogram/description/ 题目大意:在直方图中找出最大的矩形面积.例 ...
- Zabbix3.0 API调用
Zabbix API 是什么? API简单来说是服务对外开放的一个接口,用户通过该接口传递请求,完成操作.API的背后是一组方法的集合,这些方法实现了服务对应的不同功能,调用API实际上就是换了一种方 ...
- ADO.NET Connection Pooling at a Glance
ADO.NET Connection Pooling at a Glance Establishing a connection with a database server is a hefty a ...
- 【51nod】1227 平均最小公倍数
题解 这个故事告诉们数论函数不要往分式上跑,你推不出来 好久没推式子了这么明显的转化我都忘了= = 首先\(A(n) = \frac{1}{n} \sum_{i = 1}^{n} \frac{i * ...
- win7下docker环境centos容器中安装mysql5.7
docker环境基于镜像skiychan/nginx-php7,进行安装 ps:skiychan/nginx-php7此镜像已封装nginx1.15.3+php7.2.9 1.环境配置 配置共享文件夹 ...
- poj1321 棋盘问题(DFS)
题目链接 http://poj.org/problem?id=1321 题意 给定一块棋盘(棋盘可能是不规则的),有k个相同棋子,将k个棋子摆放在棋盘上,使得任意两个棋子不同行,不同列,求有多少种不同 ...