[洛谷]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;
}