【贪心】【枚举】【重庆市NOIP模拟赛】旅行

题目描述

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。

分析

这道题我考试时第一次想的是动态规划,但是我半天都没有写状态转移方程,然后就放弃了。。。做下一道题去了。。。后来我回过头来想这道题,发现可以用贪心+枚举的方法来做。
通过枚举人数t来讲目前的快乐值排序,选取前t个数求和,最大的和就是答案了。然而我在考试的时候担心程序超时,就记录了一下时间,发现最慢都只是78毫秒,于是就AC了。时间复杂度 O(n2logn)
小伙伴如果要测试程序时间,就要在编译器选项加上-Ddebug

源代码

#include
#include
#include
#include
#include
using namespace std;
int n,t,ans=-0x3f3f3f3f,ansp;
struct node{int c,d;}k[1001];
bool cmp(node x,node y){return x.c-x.d*(t-1)>y.c-y.d*(t-1);}//按照现在的快乐值排序
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&k[i].c);
    for(int i=1;i<=n;i++)
        scanf("%d",&k[i].d);
    #ifdef debug
    double a=clock();//记录起始时间
    #endif
    for(t=1;t<=n;t++){
        sort(k+1,k+n+1,cmp);//排序
        int tmp=0;
        for(int i=1;i<=t;i++)//求前t个人的快乐值的和
            tmp+=k[i].c-k[i].d*(t-1);
        if(tmp>=ans){ans=tmp;ansp=t;}//记录最大的快乐值的和
    }
    printf("%d\n%d",ans,ansp);
    #ifdef debug
    double b=clock();
    printf("\n\nn=%d\ntime:%.lf ms\n==================\n\n",n,b-a);//输出程序所用时间
    #endif
}

你可能感兴趣的:(#,C++,#,School,OJ,#,贪心)