杭电OJ 1789(贪心)

Doing Homework again

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9782    Accepted Submission(s): 5726


Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
 

Input
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.
 

Output
For each test case, you should output the smallest total reduced score, one line per test case.
 

Sample Input
   
   
   
   
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
 

Sample Output
   
   
   
   
0 3 5
 

Author
lcy

挂科问题永远都是搞ACM的兄弟们的痛苦...一边想全身心的投入题目当中,还得算计好时间复习,熬夜搞突击...伤不起....

题目大意:

给出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;//如果预定不到日期,就只能放弃了
           }
       }

然后是完整的AC代码:

#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);
    }
}
















你可能感兴趣的:(算法,杭电,贪心,贪心,贪心,杭电OJ1789,杭电1789)