bzoj 3111 蚂蚁 动态规划
题目描述
在一个 n*m 的棋盘上,每个格子有一个权值,初始时,在某个格子的顶点处一只面朝北的蚂蚁,我们只知道它的行走路线是如何转弯,却不知道每次转弯前走了多长。
蚂蚁转弯是有一定特点的,即它的转弯序列一定是如下的形式:右转,右转,左转,左转,右转,右转…左转,左转,右转,右转,右转。即两次右转和两次左转交替出现的形式,最后两次右转(最后两次一定是右转)后再多加一次右转。我们还知道,蚂蚁不会在同一个位置连续旋转两次,并且蚂蚁行走的路径除了起点以外,不会到达同一个点多次,它最后一定是回到起点然后结束自己的行程,而且蚂蚁只会在棋盘格子的顶点处转弯。

现在已知棋盘大小、每个格子的权值以及左转次数/2 的值,问蚂蚁走出的路径围出的封闭图形,权值之和最大可能是多少。
输入输出格式
输入格式:
在输入文件ant.in 中,第一行三个数n,m,k。意义如题目描述。
接下来一个n 行m 列的整数矩阵,表示棋盘。
输出格式:
一个数,表示蚂蚁所走路径围出的图形可能的最大权值和。
输入输出样例
说明
【样例说明】
除了第一行的第二个和第一行的第四个都要围起来才至少合法。
【数据规模与约定】
10%的数据所有格子中权值均非负
另20%的数据n=2
另30%的数据k=0
100%的数据1≤n≤100,1≤m≤100,0≤k≤10 保证存在合法路径,数据有梯度,格子中每个元素的值绝对值不超过 10000
P3335 这个题思维难度还是有的。。(至少我是这么想的。。大佬就别吐槽我了)
首先,通过题目描述,我们可以在纸上画一画,可以发现,图像一定是像长城一样的
就是好多个矩形它们的底在一条直线上,高和宽不同,而且,还有一点就是它是高低相间的
而且由右转形成高峰,由左转形成低谷。
那么我们可以枚举图的右下角(i,j),那么有两种情况:
一:第j-1列和第j列在同一个矩形里;
二:第j-1列和第j列在不同的矩形里;
我们要记录的状态与点(i,j),p(指的是当前枚举的是第p个矩形),h(当前枚举的举行高度为i-h+1)有关
所以用f[i][j][p][h]来记录‘一’情况的状态,用g[i][j][p][h][0/1]来记录‘二’情况的状态
这里0表示上一个矩形高度高于h,1表示低于h;
那么转移就好写了:
f[i][j][p][h]=max(f[i][j-1][p][h],g[i][j-1][p-1][h][p%2])+s[i][j]-s[h-1][j];
对了,这里这个s数组求的是每一列的前缀和,可以在输入中预处理出来,方便计算用;
关于g数组的维护,我们已经维护出f数组的第j列了
那么这一列所在的矩形要么是低谷,要么是高峰,我们都要考虑
->高峰:
g[i][j][p][h][0]=max(f[i][j][p][h-1],g[i][j][p][h-1][0]);
->低谷:
g[i][j][p][h][1]=max(f[i][j][p][h+1],g[i][j][p][h+1][1]);
当然我们可以在计算过程中更新答案,还可以省掉i这一维
因为从方程中就可以看出来i其实没有参与转移
#pragma GCC optimize(2)
#pragma G++ optimize(2)
#pragma GCC target ("avx")
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
const int Inf=;
int n,m,k,ans;
int a[maxn][maxn];
int f[maxn][][maxn];
int g[maxn][][maxn][];
int s[maxn][maxn];
void ini()
{
scanf("%d%d%d",&n,&m,&k);
//因为有2*k次左转,所以总矩形数就是k*2+1
k=k*+;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
scanf("%d",&a[i][j]);
s[i][j]=s[i-][j]+a[i][j];
}
}
//预处理 因为要求最大值,所以边界赋值为-Inf;
for(int p=;p<=k;p++)
{
for(int h=;h<=n;h++)
{
f[][p][h]=-Inf;
g[][p][h][]=-Inf;
g[][p][h][]=-Inf;
}
}
}
void dp()
{
ans=-Inf;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
for(int p=;p<=k;p++)
{
for(int h=i;h>=;h--)//维护f数组
{
f[j][p][h]=max(f[j-][p][h],g[j-][p-][h][p%])+s[i][j]-s[h-][j];
}
//维护g数组
g[j][p][][]=-Inf;
//0指当前矩形比下一个高,所以从高到低更新,才可以确保取最大值的矩形一定是高的
for(int h=;h<=i;h++)
{
g[j][p][h][]=max(f[j][p][h-],g[j][p][h-][]);
}
g[j][p][i][]=-Inf;
//1指当前矩形比下一个底,所以从低到高更新,才可以确保取最大值的矩形一定是低的
for(int h=i-;h>=;h--)
{
g[j][p][h][]=max(f[j][p][h+],g[j][p][h+][]);
}
}
//更新答案,因为最后一列一定是高的,所以用0转移;
ans=max(ans,max(f[j][k][i],g[j][k][i][]));
}
}
}
int main()
{
ini();//读入一些数据
dp();
printf("%d\n",ans);
return ;
}
bzoj 3111 蚂蚁 动态规划的更多相关文章
- BZOJ 3111: [Zjoi2013]蚂蚁寻路
Sol DP. 首先观察转折,画画图,看看移动路线,可以非常轻易的发现如果走到起点的下方是回不去的.. 然后它就相当于一个底部是平的,顶部凹凹凸凸的形状,每右转两次或左转两次就会形成小矩阵,这样就可以 ...
- bzoj 5185 Lifeguards - 动态规划 - 贪心
题目传送门 传送点I 传送点II 题目大意 给定$n$个区间,问恰好删去其中$k$个,剩下的区间的并的最大总长度. 显然被包含的区间一定不优.再加上被包含的区间对计数不友好.直接把它删掉. 注意到题目 ...
- bzoj 4621: Tc605 动态规划
题解: 一道比较简单的题目 想着想着就把题目记错了..想成了可以把某段区间覆盖为其中一个数 其实是比较简单的 每个点的贡献一定是一个区间(就跟zjoi2018那题一样) 然后问题就变成了给你n个区间让 ...
- bzoj 4318 OSU! - 动态规划 - 概率与期望
Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1 ...
- 3111: [Zjoi2013]蚂蚁寻路 - BZOJ
题目描述 Description在一个 n*m 的棋盘上,每个格子有一个权值,初始时,在某个格子的顶点处一只面朝北的蚂蚁,我们只知道它的行走路线是如何转弯,却不知道每次转弯前走了多长.蚂蚁转弯是有一定 ...
- bzoj 4767 两双手 - 动态规划 - 容斥原理
题目传送门 传送门I 传送门II 题目大意 一个无限大的棋盘上有一只马,设马在某个时刻的位置为$(x, y)$, 每次移动可以将马移动到$(x + A_x, y + A_y)$或者$(x + B_x, ...
- bzoj 3522 / 4543 [POI 2014] Hotel - 动态规划 - 长链剖分
题目传送门 bzoj 3522 需要root权限的传送点 bzoj 4543 快速的传送点 慢速的传送点 题目大意 给定一棵树,问有多少个无序三元组$(x, y, z)$使得这三个不同点在树上两两距离 ...
- bzoj 1304 [CQOI 2009] 叶子的染色 - 动态规划
题目传送门 快速的传送门 慢速的传送门 题目大意 给定一棵无根树,每个点可以染成黑色或者白色,第$i$叶节点到根的路径上最后有颜色的点必须为$c_{i}$(叶节点可以染色).问最少要染颜色的点的个数. ...
- bzoj 4044 Virus synthesis - 回文自动机 - 动态规划
题目传送门 需要高级权限的传送门 题目大意 要求用两种操作拼出一个长度为$n$的只包含'A','T','G','C'的字符串 在当前字符串头或字符串结尾添加一个字符 将当前字符串复制,将复制的串翻转, ...
随机推荐
- tcl之控制流-break/continue
- 第三章 文件 I/O
3.1 引言 先说明可用的文件 I/O 函数:open.read.write.close,然后说明不同缓冲区长度对read和write函数的影响. 本章所说的函数经常被称为不带缓冲的 I/O (unb ...
- python-1基础总结
输入 >>> name = input() 1--如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r''表示''内部的字符串默认不转义,可以自己试 ...
- 课后题2.87&2.86
课后题2.86&2.87 单纯就是想加点分第十章的题目都被做过了就做下第二章的,正好复习一下前面学的知识,第二章给我剩下的题目也不多了,我就挑了这个题目. 2.86 考虑一个基于IEEE浮点格 ...
- EVALUation mode running with code size limit:2k keil进行仿真过程中出现的报错
EVALUation mode running with code size limit:2k 如果keil软件未破解,会限制程序的存储大小.第一是你的软件没有破解,不能编译2K以上的程序:这种情况下 ...
- 开启虚拟机所报的错误:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary fil
当我们开启虚拟机时出现错误: VMware Workstation cannot connect to the virtual machine. Make sure you have rights t ...
- 原子操作和volatile关键字
原子操作:不可被中断的操作.要么全执行,要么全不执行. 现代CPU读取内存,通过读取缓存再写入主存.先去主存读--->写入缓存---->运行线程--->写入缓存---->写入主 ...
- 【Merge Intervals】cpp
题目: Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6], ...
- 使用python 3导入MySQLdb 报No module named 'MySQLdb'异常错误
MySQLdb只支持Python2.*,还不支持3.* 可以用PyMySQL代替安装PyMySQL后,在使用模块时使用import pymysql as MySQLdb 后续使用方式与MySQLdb ...
- 【转载】总结使用Unity3D优化游戏运行性能的经验
流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏<Shadow Blade>已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标. 以下是我们在紧凑的优化过程中 ...