Mr_H旗下的 n 个OIer坐船外出旅行!
但是他们只有一艘船,虽然船能装下全部的Oier,但太拥挤将会影响众OIer的心情,所以Mr_H决定选择一部分Oier去。我们假设,每个人单独坐船的快乐程度是Ci,而船上每多一个人,他的快乐程度会减去Di。
现在你的任务是帮助Mr_H计算,选择那些人,才能使船上所有人的快乐程度之和达到最大。
【输入格式】
第1行是一个整数n,表示OIer的人数;
第2行有n个整数,第i个整数表示第i个人人单独坐船的快乐程度Ci(1<=Ci<=10000);
第3行有n个整数,第i个整数表示每多1人,第i个人快乐程度的下降值Di(1<=Di<=10)。
【输出格式】
第1行一个整数,是最大的快乐程度之和;
第2行一个整数,是最大的快乐程度之和所对应的汽艇上的人数(若有多种方案,则输出人数最多的)。
【输入样例】
6
10 10 10 10 10 9
2 2 2 2 2 3
【输出样例】
18
3
【样例解释】
前3个人去坐汽艇可使快乐程度之和达到最大,每个人的快乐程度均为10-2*2=6,总和是18。
【数据范围】
对于30%的数据,n<=20;
对于100%的数据,n<=1000。
【来源】
原创命题做题思路(正解):这道题的主要算法为贪心算法,因为我们不知道最终汽艇上有多少人,所以先枚举汽艇上的人数k,按每个人此时的快乐程度由大到小排序,选择前k个快乐程度最大的人(贪心策略),然后计算出的快乐程度之和取最大值,即为所求。需要注意的是,如果有多种方案,要输出人数最多的。
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=1005; int N,k; struct data { int c,d; }; data a[maxn]; bool cmp(data aa,data bb) { return aa.c-(k-1)*aa.d>bb.c-(k-1)*bb.d; //注意,计算快乐程度时,人数要减去自己 } int main() { freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); scanf("%d",&N); for(int i=1;i<=N;i++) scanf("%d",&a[i].c); for(int i=1;i<=N;i++) scanf("%d",&a[i].d); int ans=0,cnt=0; for(k=1;k<=N;k++) //依次枚举有k个人在汽艇上,求出此时最大的快乐程度之和 { sort(a+1,a+1+N,cmp); //按此时每个人的快乐程度由大到小排序 int sum=0; for(int i=1;i<=k;i++) sum+=a[i].c-(k-1)*a[i].d; if(sum>ans || (sum==ans && cnt<k)) //如果有多种方案,输出人数最多的 { ans=sum; cnt=k; } } printf("%d\n",ans); printf("%d\n",cnt); return 0; }
考后反思:对于某些未知变量且这些变量范围较小时,可以枚举,同时,找准贪心策略是非常重要的。