HDU 1789 Doing Homework again(贪心)

本文介绍了一种解决ACM/ICPC竞赛中家庭作业调度问题的算法,通过将作业按截止日期排序,并采用贪心策略来确定完成作业的最优顺序,以最小化因延迟提交而产生的总扣分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题解:

这是团队赛比赛的一题,因为之前在做并查集和最小生成树的题,这题丢给了老刘,他也一遍过了,比完赛把这题补上,我也想了好一会,思路就是贪心,先把得到的数据按照数截止日期从小到大排序,如果相同按罚时从大到小排,然后把vis数组置为0,排好序后从前往后遍历,如果当前天数小于等于截止日期,就直接当前日期+1,否则,从已经加入套餐的中找到罚时比当前小的中最小的,记录下下标,找到了就把标记换成当前,以前的消掉,总罚时加上找到的那个的罚时,没找到直接加上当前罚时

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<string>
#include<stdio.h>
#include<queue>
#include<stack>
#include<map>
#include<deque>
using namespace std;
struct node
{
    int d;
    int p;
};
int cmp(node x,node y)//按截止日期从小到大排,如果相同就按罚时大的在前
{
    if(x.d!=y.d)
        return x.d<y.d;
    return x.p>y.p;
}
node a[1005];
int vis[1005];//遍历数组
int main()
{
    int test;
    scanf("%d",&test);
    while(test--)
    {
        int n;
        scanf("%d",&n);
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            scanf("%d",&a[i].d);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i].p);
        sort(a,a+n,cmp);
        int t=0,s=0;
        for(int i=0;i<n;i++)
        {
            if(t<a[i].d)//如果小于等于当前天数,就直接标记下天数+1,因为是从0开始所以这里填小于
            {
                vis[i]=1;
                t++;
            }
            else//不符合就先往前找已经加入套餐的有没有比这罚时更小的,有就找其中最小的
            {
                int b=i;
                for(int j=i-1;j>=0;j--)
                {
                    if(vis[j]&&a[j].p<a[b].p)//找最小的
                    {
                        b=j;//找到了记录下标
                    }
                }
                if(b!=i)//找到了
                {
                    vis[b]=0;
                    vis[i]=1;
                    s+=a[b].p;
                }
                else//没找到
                    s+=a[i].p;
            }
        }
        printf("%d\n",s);
    }
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值