E - Doing Homework again

 

在大多数的比赛中,可以使用贪心思想解决的题目,都是属于简单题一类的,之所以简单并不是说想都不用想就可以求出答案来的,相反,有些题目甚至想破头皮也想不出来,但是一看解题报告,却发现写法相当简单,难的是正确的贪心策略想不到。所以,我们说,贪心题的关键时找一个正确、有效的策略,使得结果最优。如何去找呢?先不忙,首先应该确定的是有没有这样的策略?了解过贪心算法的人,应该知道并不是所有的问题都可以使用它来解决的,原因就是贪心仅仅关注了局部的最优解。所以,当我们判断一个问题能不能使用贪心策略解决时,可以参考如下规则:

1、整体可以化为局部。

2、局部存在最优解。

3、局部与局部之间满足无后效性(即当前所做策略不会影响以前的状态)。

4、局部最优解可以推出整体最优解。

如果确定一个问题可以使用贪心求解,那么该如何求解呢?其实这个过程并没有固定的算法,问题的关键是贪心策略的选择。所以,下面仅仅给出一般过程:

1、选取问题的某个状态作为初始状态,并以此作为出发点。

2、循环求解,在这个过程中,根据我们采取的贪心策略,求出局部最优解。

3、利用局部最优解求出整体最优解。

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
 

题意:

有n门课,每一门课有一个限定的时间和超过时间后罚的分数,然后假定每一天只能完成一门课,问如何安排时间去完成这些课,使得罚分最少并输出。

分析:

先排序,将分数多的放在前面优先安排完成,这样损失就最小。将每一个作业都试图安排在最后一天完成,如果当天已经提前安排了,那么就往前面寻找,一旦发现前面还有空闲就立刻安排进去,否则该作业就无法完成,由于提前确定的作业都是分数多的作业,而且每一次安排以此作业都试图将之安排在尽量靠近最后期限的日子,以求给其他作业流出时间,所以是贪心

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
typedef struct
{  int a,b;
}P;
bool cmp(P x,P y)
{  if(x.b!=y.b)///b为分数
     return x.b>y.b;  //
   return x.a<y.a;
}
int flag[1010];
int main()
{
    int N,i,T,j,gra,t;P sp[1010];

    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
    for(i=0;i<N;i++)scanf("%d",&sp[i].a);
    for(i=0;i<N;i++)scanf("%d",&sp[i].b);
    
    sort(sp,sp+N,cmp);

    t=1;gra=0;
    memset(flag,0,sizeof(flag));
    for(i=0;i<N;i++)
    {
        for( j=sp[i].a;j>0;j--)///第i个作业需要在j=sp[i].a天内做完
        { ///将该作业在作业期限的最后一天,一直向下扫描,当遇到改天已被安排,往前一天排查,如果没有安排则该作业可以做完
            if(!flag[j])
            {
                flag[j]=1;break;
            }///如果一直没找到,那该门作业放弃,减分数
        }
        if(j==0)
           gra+=sp[i].b;
        }
        printf("%d\n",gra);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值