hdu1789(贪心)

题意:Ignatius有N项作业要完成。每项作业都有限期,如果不在限期内完成作业,期末考就会被扣相应的分数。给出测试数据T表示测试数,每个测试以N开始(N为0时结束),接下来一行有N个数据,分别是作业的限期,再有一行也有N个数据,分别是若不完成次作业会在期末时被扣的分数。求出他最佳的作业顺序后被扣的最小的分数。(每个作业费时一天)。
思路:使用一个结构体保存每门作业的限制时间和被扣的分数。
对限制时间排序,限制越大的要越先完成,若托限制时间一样,则把被扣分数大的排在前面,保证被扣分数达的要先完成。这就保证了完成的作业数做多。但是这样排序后,产生了一个问题,完成的作业数做多,被扣的分数不一定是最小;
所以做法是:设一个mark数组,标记能够完成的。然后对排序后的结构体数据进行for循环,遇到(day < deadline(即现在的时间不超过限制时间)则表示这个作业可以完成,)
{所以day++,同时mark[i]要标记这个作业可以完成。}
Else(day>=deadline,则证明这个作业放在这里做没办法完成的。)
{
考虑在前面标记过的可完成的作业,是否有某个作业的reduce比目前的ruduce小。
If(如果有)
{则证明,可以选择完成当前的这个作业,而不完成前面reduce比当前小的作业,所以两个作业的reduce交换。}
Else(如果没有)
{则什么都不操作,进入下一次循环}
}

代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
struct node
{
    int x,y;
}a[1005];
int mark[1005];
bool cmp(const node t1,const node t2)
{
    if(t1.x!=t2.x)
        return t1.x<t2.x;
    else
        return t1.y>t2.y;
}
int search(node b[],int v,int w)
{
    int zz=-1,min=v;
    for(int i=0;i<w;i++)
        if(mark[i]&&min>b[i].y)
        {
            min=b[i].y;
            zz=i;
        }
    return zz;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        int n,i,j,s=0,min;
        scanf("%d",&n);
        memset(mark,0,sizeof(mark));
        for(i=0;i<n;i++)
            scanf("%d",&a[i].x);
        for(i=0;i<n;i++)
            scanf("%d",&a[i].y);
        sort(a,a+n,cmp);
        min=a[0].y;
        int day=1;
        for(i=0;i<n;i++)
            if(day<=a[i].x)
            {
                day++;
                mark[i]=1;
            }
            else
            {
                int ex=search(a,a[i].y,i);
                if(ex!=-1)
                {
                    int cc=a[ex].y;
                    a[ex].y=a[i].y;
                    a[i].y=cc;
                }
                s=s+a[i].y;
            }
        printf("%d\n",s);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值