E - 不爱学习的lyb HDU - 1789(贪心策略)

众所周知lyb根本不学习。但是期末到了,平时不写作业的他现在有很多作业要做。
CUC的老师很严格,每个老师都会给他一个DDL(deadline)。 如果lyb在DDL后交作业,老师就会扣他的分。
现在假设lyb做作业都需要一天。 所以lyb想到要安排做作业的顺序,这样才能尽可能扣少一点分。 请帮帮bx吧。 Input
输入包含T个测试用例。输入的第一行是单个整数T,为测试用例的数量。 每个测试用例以一个正整数N开头(1<=N<=1000),表示作业的数量。
然后两行。第一行包含N个整数,表示DDL,下一行包含N个整数,表示扣的分。 Output
对于每个测试用例,您应该输出最小的总降低分数,每个测试用例一行。

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

Hint 上方有三组样例。 对于第一组样例,有三个作业它们的截止日期均为第三天,每天做一个正好在截止日期前全部做完,所以没有扣分,输出0。
对于第二组样例,有三个作业,它们的截止日期分别为第一天,第三天、第一天。第一天做了第一个作业,第二天做了第二个作业,共扣了3分,输出3。

思路

  • 题意:给我们 n 门作业,分别给我们了n们做的截止日期可过来截止日所扣的分数。从第0天开始,每天只可以做一门作业(这个养的话)一定有作业做不完,选择一个做作业的顺势是所扣分数最小,问这个最小分数是多少
  • 分析
    1. 这一让我们求扣的最少,其实就让我们找出一个贪心策略。
    2. 我一开始是 先按截止日期排序,在按扣分的大小从大到小排序,这其实是不对了,这样的话我们没法保证 扣分大作业的近两倍完成,争却的 排序方案是:按作业扣分大的排在前边,之后 对于排在前边扣分大的作业我们应该尽量 让其在最后它截止到那一天被完成(这样能保证利益最大化),如果那一天被之前更大扣分更大的作业占用的话(既然这一天被更大的扣分作业所占用的话,我们肯定是不亏的),那么就看这一天的前一天,看是否被更大的扣分作业占用,如果没有被占用的话 就在在这一天完成,如果仍备占用的话,继续向前天搜索,知道搜索到第0天的话,那说明这个作业是没法被完成的,所以 ans + 这个作业扣的分

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int mxn = 1005;
struct  Data
{
    int a, b;
    bool operator < (const Data x) const
    {
        return b > x.b;
    }
} data[mxn];


int main()
{
    /* freopen("A.txt","r",stdin); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)
            scanf("%d", &data[i].a);
        for(int i = 1; i <= n; i ++)
            scanf("%d", &data[i].b);
        sort(data + 1, data + 1 + n);
        int vis[mxn] = {0};
        int f;
        int ans = 0;
        for(int i = 1; i <= n; i ++)
        {
            f = data[i].a;
            while(vis[f])
                f --;
            if(f != 0)
                vis[f] = 1;
            else
                ans += data[i].b;
        }
        printf("%d\n", ans);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lql-nyist/p/12661393.html