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

现在已知棋盘大小、每个格子的权值以及左转次数/2 的值,问蚂蚁走出的路径围出的封闭图形,权值之和最大可能是多少。
输入输出格式
输入格式:
在输入文件ant.in 中,第一行三个数n,m,k。意义如题目描述。
接下来一个n 行m 列的整数矩阵,表示棋盘。
输出格式:
一个数,表示蚂蚁所走路径围出的图形可能的最大权值和。
输入输出样例
2 5 2
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-8
说明
【样例说明】
除了第一行的第二个和第一行的第四个都要围起来才至少合法。
【数据规模与约定】
10%的数据所有格子中权值均非负
另20%的数据n=2
另30%的数据k=0
100%的数据1≤n≤100,1≤m≤100,0≤k≤10 保证存在合法路径,数据有梯度,格子中每个元素的值绝对值不超过 10000
题解:
首先需要看明白题,什么左转右转的
自己举几个例子就可以知道,围成的图形大概长这样:

凹进去几个,就是k(比如上图k=3)
然后,其实挺明显能看出来是dp
但怎么dp是个问题!想了好久好久
一开始我是将围成的图形拆成k*2+1个矩形来想,但后来发现可以一列一列考虑
dp[i][j][h][l]表示当前起点在第i行,考虑到第j列,当前高度为h(指的是顶上那个点的行数),还可或起或伏l次(包括本次的)
dp[i][j][h][l]=max(dp[i][j+1][h][l],dp[i][j+1][h'][l-1])
前者是第j+1列与当前列高度相同(说白了在一个矩形中),后者h'就是第j+1列应比这列的高还是矮(取决于l的奇偶)
发现h'如果一个一个枚举好慢啊,那就开两个数组记录一下好了
写题时细节很多,感觉整个人都不好了……不可思议的是居然过了,还是很开心的
注意:提交的第一次只有60分,剩下的MLE了……所以说下次要注意数组大小!!!
代码:
#include<cstdio>
#include<iostream>
#define INF 100000000
using namespace std; const int MAXN = ;
int dp[MAXN][MAXN][MAXN][];
int big[MAXN][MAXN][],sml[MAXN][MAXN][];
int a[MAXN][MAXN],sum[MAXN][MAXN];
int n,m,k; int num(int y,int x0,int x){
return sum[x][y]-sum[x][y-]-sum[x0-][y]+sum[x0-][y-];
} int main()
{
int i,j,w,h,l,s;
scanf("%d%d%d",&n,&m,&k);
w=*k+;
for(i=;i<=n;i++) sum[i][]=;
for(i=;i<=m;i++) sum[][i]=;
for(i=;i<=n;i++)
for(j=;j<=m;j++){
scanf("%d",&a[i][j]);
sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+a[i][j];
} for(i=;i<=n;i++)
for(j=;j<=m;j++)
for(h=;h<=n+;h++)
for(l=;l<=w;l++)
dp[i][j][h][l]=-INF; for(i=;i<=n;i++){
for(j=;j<=m;j++)
for(h=;h<=n+;h++)
for(l=;l<=w;l++) big[j][h][l]=sml[j][h][l]=-INF;
for(j=m;j>=;j--){
for(l=;l<=(m-j+) && l<=w;l++){
for(h=;h<=i;h++){
s=num(j,h,i);
if(l==) {
if(j==m) dp[i][j][h][l]=s;
else dp[i][j][h][l]=s+max(,dp[i][j+][h][l]);
}
else{
if(l%==)
dp[i][j][h][l]=max(dp[i][j+][h][l],big[j+][h+][l-])+s;
else
dp[i][j][h][l]=max(dp[i][j+][h][l],sml[j+][h-][l-])+s;
}
}
sml[j][][l]=dp[i][j][][l];
for(h=;h<=i;h++) sml[j][h][l]=max(sml[j][h-][l],dp[i][j][h][l]);
big[j][i][l]=dp[i][j][i][l];
for(h=i-;h>=;h--) big[j][h][l]=max(big[j][h+][l],dp[i][j][h][l]);
}
}
} int ans=-INF;
for(i=;i<=n;i++)
for(j=;j+w-<=m;j++)
for(h=;h<=i;h++) ans=max(ans,dp[i][j][h][w]);
printf("%d\n",ans); return ;
}
洛谷P3335 [ZJOI2013]蚂蚁寻路的更多相关文章
- bzoj3111: [Zjoi2013]蚂蚁寻路
题目链接 bzoj3111: [Zjoi2013]蚂蚁寻路 题解 发现走出来的图是一向上的凸起锯齿状 对于每个突出的矩形dp一下就好了 代码 /* */ #include<cstdio> ...
- 3111: [Zjoi2013]蚂蚁寻路 - BZOJ
题目描述 Description在一个 n*m 的棋盘上,每个格子有一个权值,初始时,在某个格子的顶点处一只面朝北的蚂蚁,我们只知道它的行走路线是如何转弯,却不知道每次转弯前走了多长.蚂蚁转弯是有一定 ...
- 洛谷P1916 小书童——蚂蚁大战
题目背景 小A在你的帮助下,开始“刷题”,他在小书童里发现了一款叫“蚂蚁大战”(又称蛋糕保卫战)的游戏.(你懂得) 题目描述 游戏中会出现n只蚂蚁,分别有a1,a2……an的血量,它们要吃你的蛋糕.当 ...
- 洛谷 P3332 [ZJOI2013]K大数查询 解题报告
P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...
- 洛谷——P1916 小书童——蚂蚁大战
P1916 小书童——蚂蚁大战 题目背景 小A在你的帮助下,开始“刷题”,他在小书童里发现了一款叫“蚂蚁大战”(又称蛋糕保卫战)的游戏.(你懂得) 题目描述 游戏中会出现n只蚂蚁,分别有a1,a2…… ...
- 【洛谷P1367】蚂蚁
蚂蚁 [题目描述] 在一根无限长的木棍上,用n只蚂蚁,每只蚂蚁有一个初始位置和初始朝向,蚂蚁们以每秒一个单位的速度向前移动,当两只蚂蚁相遇时,它们会掉头(掉头时间忽略不计).现给出每只蚂蚁的初始位置和 ...
- 洛谷 P1916 小书童——蚂蚁大战
P1916 小书童——蚂蚁大战 题目背景 小A在你的帮助下,开始“刷题”,他在小书童里发现了一款叫“蚂蚁大战”(又称蛋糕保卫战)的游戏.(你懂得) 题目描述 游戏中会出现n只蚂蚁,分别有a1,a2…… ...
- BZOJ 3111: [Zjoi2013]蚂蚁寻路
Sol DP. 首先观察转折,画画图,看看移动路线,可以非常轻易的发现如果走到起点的下方是回不去的.. 然后它就相当于一个底部是平的,顶部凹凹凸凸的形状,每右转两次或左转两次就会形成小矩阵,这样就可以 ...
- [洛谷P3332][ZJOI2013]K大数查询
题目大意:有$n$个位置,$m$个操作.操作有两种: $1\;l\;r\;x:$在区间$[l,r]$每个位置加上一个数$x$ $2\;l\;r\;k:$询问$[l,r]$中第$k$大的数是多少. 题解 ...
随机推荐
- C# 高级面试题
很少会有人可以答对,如果你遇到一个来面试的人实在嚣张,就可以用本文的题去打击 本文内容就看着玩,请不要在严肃的面试中问题这样的题目 如果面试到一个人可以回答出下面的题目也不能证明他的技术很强,只能说明 ...
- new Date(2019-08-24 12:30:00)和new Date(2019-08-29T02:15:08.000+0000)在ios的兼容NAN问题
new Date()在安卓和pc端上正常显示,但是却在ios上显示 NAN的问题 正常写法: var time = new Date("2019-08-24 12:30:00"); ...
- 牛客小白月赛15A 斑羚飞渡
链接:https://ac.nowcoder.com/acm/contest/917/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K 64b ...
- koa2入门--01.ES6简单复习、koa2安装以及例子
1.ES6简单复习 /*let 和 const: let用于定义一个块作用域的变量,const 定义一个常量 */ let a = 'test'; const b = 2; /*对象的属性和方法的简写 ...
- Java并发机制的底层实现原理之volatile应用,初学者误看!
volatile的介绍: Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现 ...
- linux 没有音频输出的解决方式
用户级别的-/.asoundrc 文件. 如果文件不存在,可以手动创建. 其中的各个 ID,请根据实际情况调整: defaults.pcm.card 1 defaults.pcm.device 0 d ...
- JS-数组常用方法整理
想了解数组有哪些原生方法,控制台输出,如图: length:数组的实例属性,返回或设置一个数组中的元素个数. toString():可以把数组转换成字符串,并返回结果. toLocaleString( ...
- 洛谷$P5446\ [THUPC2018]$绿绿和串串 $manacher$
正解:$manacher$ 解题报告: 传送门$QwQ$ 考虑这个操作的实质是啥$QwQ$?其实就,变成以最后一个节点为回文中心的回文子串嘛$QwQ$.显然就先跑个马拉车再说呗$QwQ$. 然后接着考 ...
- Head First设计模式——组合模式
最近比较忙,有段时间没有更新设计模式的进度了.今天继续学习组合设计模式. 组合模式的例子我们继续延续上篇<Head First设计模式——迭代器模式>的菜单例子,首先声明下迭代器和组合模式 ...
- POJ2411 Mondriaan's Dream 题解 轮廓线DP
题目链接:http://poj.org/problem?id=2411 题目大意 给你一个 \(n \times m (1 \le n,m \le 11)\) 的矩阵,你需要用若干 \(1 \time ...