推销员【贪心】

>Description
阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。

阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。


>Input
第一行有一个正整数N,表示螺丝街住户的数量。
接下来的一行有N个正整数,其中第i个整数Si,表示第i家住户到入口的距离。数据保证S1≤S2≤…≤Sn<10^8
接下来的一行有N个正整数,其中第i个整数Ai,表示向第i户住户推销产品会积累的疲劳值。数据保证Ai<1000

>Output
输出N行,每行一个正整数,第i行整数表示当X=i时,阿明最多积累的疲劳值。


>Sample Input
5
1 2 2 4 5
5 4 3 4 1

>Sample Output
12
17
21
24
27


>解题思路
看到题目想了一下准备用贪心,但是发现自己的贪心算法有很多bug打不下去,所以看了一下题解(豁然开朗)。

首先考虑疲劳值A,路程先不管,所以得出的ans在X的情况下为
a n s = s u m ( a [ 1   X ] ) + 2 ∗ 前 X 中 路 程 最 大 值 ans=sum(a[1 ~ X])+2*前X中路程最大值 ans=sum(a[1 X])+2X

但是也有可能后面没选的a值较小的加上路程会大于选了的数,所以我们需要舍弃a值第X大的数(不能舍弃两个,是因为后面最大的路程加上两个较小的a,还不如后面最大的路程只加上一个小a,留下一个大a),这时的ans为
a n s = s u m ( a [ 1   X − 1 ] ) + a [ 在 后 面 选 中 的 数 ] + 2 ∗ 选 中 的 路 程 ans = sum(a[1 ~ X-1])+a[在后面选中的数]+2*选中的路程 ans=sum(a[1 X1])+a[]+2

这样做一下预处理就会简单很多了


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct ooo
{
	int s, c;
} a[100005];
int n, f[100005], x[100005], y[100005];

bool bmp (ooo aa, ooo bb) {return aa.c > bb.c;}

int main()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++) scanf ("%d", &a[i].s);
	for (int i = 1; i <= n; i++) scanf ("%d", &a[i].c);
	sort (a + 1, a + 1 + n, bmp); //按照a排序
	
	for (int i = 1; i <= n; i++) f[i] = f[i - 1] + a[i].c; //a前缀和
	for (int i = 1; i <= n; i++) x[i] = max (x[i - 1], a[i].s); //前i中路程最大的
	for (int i = n; i >= 1; i--) y[i] = max (y[i + 1], a[i].s * 2 + a[i].c);
	                                                 //后i中路程及a最大的
	
	for (int i = 1; i <= n; i++)
	  printf ("%d\n", max (f[i] + 2 * x[i], f[i - 1] + y[i + 1])); //输出最大值
	          //这里我有想过后者路程最大值仍然在前X中,但是这样的话一定是前者更大(自己想想)
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值