1. 程式人生 > >[洛谷]P2672 推銷員 (#貪心 -2.7)(#模擬 -2.8)

[洛谷]P2672 推銷員 (#貪心 -2.7)(#模擬 -2.8)

題目描述

阿明是一名推銷員,他奉命到螺絲街推銷他們公司的產品。螺絲街是一條死衚衕,出口與入口是同一個,街道的一側是圍牆,另一側是住戶。螺絲街一共有NN家住戶,第ii家住戶到入口的距離為S_iSi​米。由於同一棟房子裡可以有多家住戶,所以可能有多家住戶與入口的距離相等。阿明會從入口進入,依次向螺絲街的XX家住戶推銷產品,然後再原路走出去。

阿明每走11米就會積累11點疲勞值,向第ii家住戶推銷產品會積累A_iAi​點疲勞值。阿明是工作狂,他想知道,對於不同的XX,在不走多餘的路的前提下,他最多可以積累多少點疲勞值。

輸入輸出格式

輸入格式:

 

第一行有一個正整數NN,表示螺絲街住戶的數量。

接下來的一行有NN個正整數,其中第ii個整數S_iSi​表示第ii家住戶到入口的距離。資料保證S_1≤S_2≤…≤S_n<10^8S1​≤S2​≤…≤Sn​<108。

接下來的一行有NN個正整數,其中第ii個整數A_iAi​表示向第ii戶住戶推銷產品會積累的疲勞值。資料保證A_i<1000Ai​<1000。

 

輸出格式:

 

輸出NN行,每行一個正整數,第i行整數表示當X=iX=i時,阿明最多積累的疲勞值。

 

輸入輸出樣例

輸入樣例#1: 複製

5
1 2 3 4 5
1 2 3 4 5

輸出樣例#1:

 複製

15
19
22
24
25

輸入樣例#2: 複製

5
1 2 2 4 5
5 4 3 4 1

輸出樣例#2: 複製

12
17
21
24
27

說明

【輸入輸出樣例1說明】

X=1X=1:向住戶55推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值為55,總疲勞值為1515。

X=2X=2:向住戶4,54,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值為4+54+5,總疲勞值為5+5+4+5=195+5+4+5=19。

X=3X=3:向住戶3,4,53,4,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值3+4+53+4+5,總疲勞值為5+5+3+4+5=225+5+3+4+5=22。

X=4X=4:向住戶2,3,4,52,3,4,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值2+3+4+52+3+4+5,總疲勞值5+5+2+3+4+5=245+5+2+3+4+5=24。

X=5X=5:向住戶1,2,3,4,51,2,3,4,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值1+2+3+4+51+2+3+4+5,總疲勞值5+5+1+2+3+4+5=255+5+1+2+3+4+5=25。

【輸入輸出樣例2說明】

X=1X=1:向住戶44推銷,往返走路的疲勞值為4+44+4,推銷的疲勞值為44,總疲勞值4+4+4=124+4+4=12。

X=2X=2:向住戶1,41,4推銷,往返走路的疲勞值為4+44+4,推銷的疲勞值為5+45+4,總疲勞值4+4+5+4=174+4+5+4=17。

X=3X=3:向住戶1,2,41,2,4推銷,往返走路的疲勞值為4+44+4,推銷的疲勞值為5+4+45+4+4,總疲勞值4+4+5+4+4=214+4+5+4+4=21。

X=4X=4:向住戶1,2,3,41,2,3,4推銷,往返走路的疲勞值為4+44+4,推銷的疲勞值為5+4+3+45+4+3+4,總疲勞值4+4+5+4+3+4=244+4+5+4+3+4=24。或者向住戶1,2,4,51,2,4,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值為5+4+4+15+4+4+1,總疲勞值5+5+5+4+4+1=245+5+5+4+4+1=24。

X=5X=5:向住戶1,2,3,4,51,2,3,4,5推銷,往返走路的疲勞值為5+55+5,推銷的疲勞值為5+4+3+4+15+4+3+4+1,總疲勞值5+5+5+4+3+4+1=275+5+5+4+3+4+1=27。

【資料說明】

對於20%的資料,1≤N≤20;

對於40%的資料,1≤N≤100;

對於60%的資料,1≤N≤1000;

對於100%的資料,1≤N≤100000


思路

#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct lxydl
{
	long long int x,y,z;//x為路程,y為體力值,z為除第一個以外的最大疲勞值 
}a[100001];
int cmp(lxydl p1,lxydl p2)
{
	return p1.z>p2.z;//把大的排到前面 
}
long long int index,n;
long long int maxn,s0;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	register long long int i,j;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i].x;
	}
	for(i=1;i<=n;i++)
	{
		cin>>a[i].y; 
	}
	for(i=1;i<=n;i++)
	{
		s0=a[i].x*2+a[i].y;//因為來回一趟,所以a[i].x*2,再加上推銷的疲勞值 
		if(s0>maxn)
		{
			maxn=s0;
			index=i;//先找出第一個疲勞值最大的人家,index是那戶人家的下標 
		} 
	}
	cout<<maxn<<endl;
	for(i=1;i<index;i++)//39~47行 處理分水嶺左右兩邊的房屋 
	{
		a[i].z=a[i].y;//比index小的,不用算路程,因為分水嶺路程最大,直接加上疲勞值即可 
	}
	for(i=index+1;i<=n;i++)
	{
		a[i].z=a[i].y+(a[i].x-index)*2;//比分水嶺大的,要加上疲勞值和除了第一個以外的路程 
	}
	sort(a+1,a+index,cmp);//在小範圍內找大的值
	sort(a+index+1,a+n+1,cmp);//兩個不能合併,否則就錯了 
	for(i=1;i<index;i++) //這可以通過資料證明比index大的疲勞值沒有比小的疲勞值大,不然我的思路就是在比index大和比index小的範圍內分別找一個最大,然後比較,相加,但是老沈的思路a了(此題資料太水),我就不麻煩了 
	{
		maxn=maxn+a[i].z;
		cout<<maxn<<endl;//輸出每一次的疲勞值 
	}
	for(i=index+1;i<=n;i++)//在大範圍內一次輸出 
	{
		maxn=maxn+a[i].z;
		cout<<maxn<<endl;
	}
	return 0;
}