1 条题解
-
0
自动搬运
来自洛谷,原作者为

Rainy7
恍惚间,宝石与花朵都死去了。搬运于
2025-08-24 21:40:18,当前版本为作者最后更新于2019-07-13 20:17:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
-
前言
是介个样子,不知道是不是我太弱了,我看了好多题解,然后花了好多时间才明白贪心具体。
于是我决定自己写一题解,会详细一些的。本题解会有 贪心思路+例子模拟贪心
我觉得我挺有良心的,,希望大家都能看懂QAQ
-
题目大意
推销员阿明,要给住在某街的N个用户推销,走一米会增加1的疲劳值,第i家距离路口米(可能会有重复的)给第i家推销会增加。全部推销完,还要原路返回。
现在,依次向用户推销,对于不同的,阿明想知道最大疲劳值
-
分析
距离是真的烦人,那就不管他吧。因为想要疲劳值最大,那么先按照疲劳值从大到小排序一边。
此时,可以判断出,最大值可能为:对于每个,只要加上前大的疲劳值,再加上这些数中距离最远的并乘以2,也就是:
其中,表示前K个距离最远的,sum()表示和。
但是,推销员可以通过走远一点,虽然疲劳值比前面小,但是有可能把路程一算,反而更大。
因此,可以把,即疲劳值中,前大中的最小值,即第大的那一家舍去,看看能不能通过走更远来换取更大的疲劳值总和。
而从后面看,一定也会存在一个最大值,把这个最大值和前面个疲劳值总和加起来,看看会不会比前面第一种的情况大。
证明:只需舍去最小值来走更远,无需舍去更多数来走更远。
其实这也不是一个证明..
因为已经从大到小排序了,所以,如果舍去个疲劳值,那么后面只会在加上两个更小的疲劳值,以及两个之间最大的距离并乘2,那么这样还不如只舍去一个。
2个不行,那么2个以上更是不行了。
-
举例子了。
硬讲太累了,还是用一个例子吧。
//自动排序QAQ s[i]:1,3,4,5,11 a[i]:5,4,2,1,1若,直接取,那么值为:,如果舍去最小的往后跑,值为:,所以,最大值就为。
若,直接取,值为:,把其中最小值舍去,也就是去掉,往后跑值为:,那么最大值为。
若把次小疲劳值,即,也往后跑,那么值为,可以发现,距离并未因此改变,仍为,而位置移后,疲劳值只会减少,故只要移动最小疲劳值。
那么,最后一个问题,酱紫复杂度是会炸掉的,
用记录疲劳前缀和,这样子加的时候方便。
用记录前i个距离最大值,这样子就不用找啦!
用记录往后跑时,应该选哪个,也就是后i个的最大值。
这样子预处理,就可以实现啦!
-
代码QAQ
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; int n,sum[100010],q[100010],h[100010];//n 疲劳前缀和 前i个最大值 后i个最大值 struct node{ int s;//距离 int a;//疲劳 }v[100010]; bool cmp(node x,node y){return x.a>y.a;} int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&v[i].s); for(int i=1;i<=n;i++)scanf("%d",&v[i].a); sort(v+1,v+1+n,cmp);//按疲劳排序 for(int i=1;i<=n;i++)sum[i]=sum[i-1]+v[i].a; for(int i=1;i<=n;i++)q[i]=max(q[i-1],2*v[i].s);//前i个最大值 for(int i=n;i>=1;i--)h[i]=max(h[i+1],2*v[i].s+v[i].a);//后i个最大值 for(int i=1;i<=n;i++)printf("%d\n",max(sum[i]+q[i],sum[i-1]+h[i])); return 0; }路人七
-
- 1
信息
- ID
- 1719
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者