3 3 3 3 3 10 5 1 3 1 3 1 6 2 3 7 1 4 6 4 2 4 3 3 2 1 7 6 5 4
0 3 5
题目大意:
给出n个作业,同时表示有n天.第一行输入表示截止时间(deadline 简称dl)第二行表示如果逾期,要扣除对应的学分
读了题目马上就能知道这是一道贪心题,但是思路呢?马上想到的是最短的时间完成最多的分数啦~.
问题关键词还是锁定在了学分的身上,我们输出的是最小扣除学分,那么我们就要在有限的时间里边完成最多的高分作业,这个时候我们首先想到了排序.
学分从高到底排序:
struct homework { int dl,s; }a[1001]; int cmp(homework a,homework b) { if(a.s==b.s) { return a.dl<b.dl; } return a.s>b.s; }然后呢,我们这里边看题干的第三组样例:
我们拥有七天的时间,缺有3个4天的重复作业。我们光排了学分的顺序是远远不够的,假如这个例子排序之后的顺序如下:
4 7
2 6
4 5
3 4
1 3
4 2
6 1
我们用普通的顺序作业操作是不能能得到最优解的.所以我们这里还要做到更优才能得到我们想要的解.
这里详解实例:
假如我们先把4 7这份作业拿出来,回头看看,后边有很多事在 3 2 1天之内就要做完的啊,所以我们要考虑这样一个问题:这份作业我是先做了呢 还是等第四天最后做呢?
当然是第四天最后做了。把之前的时间让给截止时间早的作业啊。然后我们预计一下第一份作业(4 7)放在第四天做。然后我们拿出2 6这份作业,同理操作,将这份作业预定第二天去做,然后拿出4 5这份作业,这时候我们发现,第四天已经预定给了7学分的那份作业了,这份作业在第四天做的话不如刚刚预定的那样让7学分的在第四天做,这样能获得最大的学分,那么我这份 4 5的作业放在哪天做呢?这个时候我们要找到第三天的作业,相比较而言, 4 5这份作业比 3 4这份作业在第三天做获得的学分更多更划算一些。然后我们预定了这份作业在第三天去做。那么3 4这份作业又要去哪里做呢,看看第二天吧,第二天也预定了,而且第二天做的6学分的作业,比这个4学分的划算,那看看第一天吧,第一天没有预定,细心的我想去看看第一天就必须交的那份作业价值多少学分呢?找到一看 3学分,比我这个4学分低,当然要做4学分的作业啦,划算一些。这个时候把第一天预定做3 4这份作业。然后我们拿出1 3这份作业,诶,第一天我们有预定的作业了,但是第一天预定的作业获得的学分比这份作业获得的学分多,合适,我宁愿这份作业扔掉任其扣分了。然后是4 2 这份作业,也是无奈的扣掉了分,然后是6 1这份作业,第六天没有预定,然后预定第六天做这份作业,一整个整理作业的过程也就结束了。我一共扣掉了5个学分,也同时找到了最优解。
那么我们这里要处理的问题是,如何保证先预定的一定是学分高的合算的作业呢?我们刚刚有谈到排序的操作,我们排序的时候就解决了这个问题,另外的问题就是预定的问题,我们这里用一个vis[]数组就能轻松搞定。
所以这个题目的解答思路就是:给每一份作业都预定上做那份作业的时间,预定天数的同时要保证这份作业一定是要价值最高,方案最好的。我们这里就应用了排序的操作,然后就是预定天数的顺序,我们要尽量把作业放在截止的当天去做,能把大量的时间让给重复的作业和之前截止的作业。
这里贴上核心代码:
sort(a,a+n,cmp);//排序 int output=0; for(int i=0;i<n;i++) { int j=a[i].dl;//令j表示截止天数 while(j)//预定日期 { if(vis[j]==0)//如果当前日期(作业截止当天)没有预定,并且我保证了截止当天做这份作业是不亏的前提下(不愧的前提是排序) { vis[j]=1;//我们就预定了这一天 break; } j--;//否则就向前找预定的日期 } if(j==0) { output+=a[i].s;//如果预定不到日期,就只能放弃了 } }
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; struct homework { int dl,s; }a[1001]; int vis[1001]; int cmp(homework a,homework b) { if(a.s==b.s) { return a.dl<b.dl; } return a.s>b.s; } int main() { int t; scanf("%d",&t); while(t--) { memset(vis,0,sizeof(vis)); int n; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i].dl); } for(int i=0;i<n;i++) { scanf("%d",&a[i].s); } sort(a,a+n,cmp); int output=0; for(int i=0;i<n;i++) { int j=a[i].dl; while(j) { if(vis[j]==0) { vis[j]=1; break; } j--; } if(j==0) { output+=a[i].s; } } printf("%d\n",output); } }