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的更多相关文章
随机推荐
- transform的妙用---实现div不定宽高垂直水平居中
transform的兼容性 transform的兼容性还是比较乐观的.IE9以下不兼容,IE9支持代替的-ms-transform属性不过只支持2D转换. 谷歌和Safari支持代替的-webkit- ...
- Program terminated with signal SIGABRT, Aborted.
linux C++ 程序 启动后就奔溃 #0 0x00007f01ee4c21f7 in raise () from /lib64/libc.so.6 #1 0x00007f01ee4c38e8 in ...
- 剑指Offer——二叉树的深度
题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 分析: 二叉树的深度等于其左子树的深度和右子树的深度两个中最大的深 ...
- embedded-redis在单元测试中的使用
1 背景 参考链接:https://github.com/kstyrc/embedded-redis 2 使用 2.1 引入依赖 <dependency> <groupId>c ...
- 001-ant design pro 页面加载原理及过程,@connect 装饰器
一.概述 以列表页中的标准列表为主 Ant Design Pro 默认通过只需浏览器单方面就可处理的 HashHistory 来完成路由.如果要切换为 BrowserHistory,那在 src/in ...
- 010-Hadoop Hive sql语法详解5-HiveQL与SQL区别
1.Hive不支持等值连接 •SQL中对两表内联可以写成:•select * from dual a,dual b where a.key = b.key;•Hive中应为•select * from ...
- java 多线程 day07 多线程共享数据
/** * Created by chengtao on 17/12/3. * 多个线程 如何共享数据? * 常见实例:多个窗口同时售卖火车票 */public class Thread0701_Mu ...
- PHP json_encode自动转码的问题
用PHP的json_encode处理中文的时候, 中文会被编码成类似于"\u5f20\u4e09"的格式,例如: <?php $arr = array('张三','李四'); ...
- SQL Server去重和判断是否为数字——OBJECT_ID的使用
sql 语句查询时去掉重复项: 使用 distinct 去掉重复项: 首先可以明确的看到存在重复的名字,那么接下来就让我们试试使用 distinct 去重吧. select distinct * fr ...
- maven tomcat7-maven-plugin配置及背景
背景: 在研发阶段,想让一个服务通过tomcat启动起来有很多的方法,常用的idea都有这样的支持,那么如果我们没有tomcat,能不能让服务通过tomcat启动起来呢?maven就提供了这样的支持. ...