dp_train_f
题目大意:有2n个格子,分成上下两行,每行n个,每个格子有蘑菇每秒的生长值(rate),小姑娘从左上角出发(time=0),每秒必须移动,而且只能移动到相邻的格子(共享一条边),每个格子只能经过一次,一旦到达格子即获得蘑菇当前时间的总量(rate*time),终点不定,求最大的蘑菇采摘量。
题解:很早就想补这题,一直没去,刚好最近开了dp专题,就想到了这一题。其实这题挺吃思维的。首先不妨把格子编号(12n)(顺时针处理从左上到左下12n,逆时针处理从左下到左上1~2n,顺(逆)时针处理下文会提及),可以发现,由于每个格子只能经过一次,那么终点其实只有n个,因为奇数列只能是下面一行作为终点,偶数列只能是上面一行作为终点。这样一来可以发现,其实走法已经限定了,不管终点在奇数列还是偶数列(设为第i列),走法都是先从起点走↓→↑→
(设为k)的整数倍再加上一部分(不妨设为ans[0][i] = a*k+b*part_k
),然后从终点上(下面)面的格子开始走一个顺(逆)时针后(ans[1][i]),到达终点。最后枚举终点,计算答案,取最值(max { ans[0][i]+ans[1][i] | i E [1,n] }
)即可。
实现技巧:我们发现↓→↑→
走法很好统计,当算到第i列时,判断奇偶,即为ans[0][i] = ans[0][i-1]+c*a[0][i]+d*b[0][i]
(c、d为步数,根据i的奇偶很好推出)。麻烦就在右边的顺时针和逆时针怎么推,这个也是我卡了很久的地方,这个真的需要一定的观察我觉得。因为是顺(逆)时针,所以可以把最大的顺(逆)时针的答案预处理出来(sum[0][i]表示顺时针到第i个格子的答案总和,sum[1][i]即为逆时针),然后观察当起点在第i列时,答案的性质,会发现和这个最大顺(逆)时针有个(i-1)*suf[i]
(suf[i]表示从第i列到第n列的上下两行数值总和)的差值(例如第二张图,终点在第三列顺时针答案为456789,是最大顺时针234567,加上后面三列总和的两(i-1)倍),而显然这个差值是可以预处理出来的,那么这题也就解决了。
下面上图
△为答案所在位置,clock_max即为顺时针最大圈(第一个图)
sum[0][i]表示最大顺时针到第i格(i E [1,2n],顺时针编号),sum[1][i]则为逆时针。
ans[0][i]表示终点在第i列,左边↓→↑→
走法答案,ans[1][i]表示从终点上(下面)面一格开始走顺(逆)时针到达终点的答案。
PS:这篇博客个人感觉绝对通俗易懂。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define de(x) cout << #x << " = " << x << endl
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 3e5 + 16;
ll a[2][N];
ll spr[N];
ll sum[2][2*N];
ll ans[2][N];
int main()
{
int n;
scanf("%d", &n);
for ( int i = 1; i <= n; i ++ )
scanf("%I64d", &a[0][i]);
for ( int i = 1; i <= n; i ++ )
scanf("%I64d", &a[1][i]);
clr(spr,0);
clr(sum,0);
clr(ans,0);
int e = 2*n + 1;
for ( int i = n; i >= 1; i -- )
spr[i] = spr[i+1] + a[0][i]+a[1][i];
//sum[0][]clock sum[1][]co-clock
for ( int i = 1; i <= n; i ++ )
sum[0][i] = sum[0][i-1] + (i-1)*a[0][i], sum[1][i] = sum[1][i-1] + (i-1)*a[1][i];
for ( int i = n; i >= 1; i -- )
sum[0][e-i] = sum[0][e-i-1] + a[1][i]*(e-i-1), sum[1][e-i] = sum[1][e-i-1] + a[0][i]*(e-i-1);
for ( int i = 1; i <= n; i ++ )
{
if ( i & 1 )
{
ans[1][i] = sum[0][e-i] - sum[0][i-1] + (i-1)*spr[i];
ans[0][i] = ans[0][i-1] + (2*i-3)*a[0][i-1] + (2*i-4)*a[1][i-1];
}
else
{
ans[1][i] = sum[1][e-i] - sum[1][i-1] + (i-1)*spr[i];
ans[0][i] = ans[0][i-1] + (2*i-3)*a[1][i-1] + (2*i-4)*a[0][i-1];
}
}
ll mx = 0;
for ( int i = 1; i <= n; i ++ )
mx = max( mx, ans[0][i]+ans[1][i] );
printf("%I64d\n", mx);
return 0;
}
dp_train_f的更多相关文章
随机推荐
- PHP之冒号、endif、endwhile、endfor 是什么鬼?f
解释:其实这些都是PHP的语法,只不过不常用而已,这些都是PHP流程控制的替代语法. 冒号(:)相当于是 左大括号---->{ endif.endwhile.endfor.endforeach- ...
- Java 代码实现Http 的GET和POST 请求
先来个传统的,不过这个里面有些类已经标明 deprecated,所以之后还有更好的方法,起码没有被标明 deprecated的类和方法. 前两个方法是有deprecated的情况.后面用HttpURL ...
- Yii框架2.0的视图和widgets表单的使用
2.0的控制器的创建和action方法的添加和1.0的基本是一样的.但我发现他的widgets 的ActiveForm和1.1版本有些不一样的地方. 对于视图基本也是一样的,有render 和 ren ...
- 并发编程 - 线程 - 1.线程queue/2.线程池进程池/3.异步调用与回调机制
1.线程queue :会有锁 q=queue.Queue(3) q.get() q.put() 先进先出 队列后进先出 堆栈优先级队列 """先进先出 队列"& ...
- HBase 二次开发 java api和demo
1. 试用thrift python/java以及hbase client api.结论例如以下: 1.1 thrift的安装和公布繁琐.可能会遇到未知的错误,且hbase.thrift的版本 ...
- DIV+CSS如何让文字垂直居中?
在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...
- 斯坦福第二课:单变量线性回归(Linear Regression with One Variable)
二.单变量线性回归(Linear Regression with One Variable) 2.1 模型表示 2.2 代价函数 2.3 代价函数的直观理解 I 2.4 代价函数的直观理解 I ...
- [笔记] Ubuntu 18.04安装cuda 10及cudnn 7流程
安装环境 OS:Ubuntu 18.04 64 bit 显卡:NVidia GTX 1080 任务:安装 CUDA 10及cuDNN 7 工具下载 NVidia官网下载下列文件: CUDA 10:cu ...
- Eclipse下创建Maven项目(转)
原文出自:http://www.cnblogs.com/hongwz/p/5456616.html 1.新建Maven项目 1.1 File -> New -> Other 1.2 选择M ...
- QUIC协议
QUIC协议 QUIC协议参考网址 https://www.chromium.org/quic 既生瑜,何生亮? QUIC的特性 提供可靠传输 减少连接建立的时间 改善拥塞控制 多路复用 转发错误连接 ...