HDU 5188 zhx and contest 01背包的变形

题目描述:

Problem Description
As one of the most powerful brushes in the world, zhx usually takes part in all kinds of contests.
One day, zhx takes part in an contest. He found the contest very easy for him.
There are n problems in the contest. He knows that he can solve the ith problem in ti units of time and he can get vi points.
As he is too powerful, the administrator is watching him. If he finishes the ith problem before time li, he will be considered to cheat.
zhx doesn’t really want to solve all these boring problems. He only wants to get no less than w points. You are supposed to tell him the minimal time he needs to spend while not being considered to cheat, or he is not able to get enough points.
Note that zhx can solve only one problem at the same time. And if he starts, he would keep working on it until it is solved. And then he submits his code in no time.

Input
Multiply test cases(less than 50). Seek EOF as the end of the file.
For each test, there are two integers n and w separated by a space. (1≤n≤30, 0≤w≤109)
Then come n lines which contain three integers ti,vi,li. (1≤ti,li≤105,1≤vi≤109)

Output
For each test case, output a single line indicating the answer. If zhx is able to get enough points, output the minimal time it takes. Otherwise, output a single line saying “zhx is naive!” (Do not output quotation marks).

Sample Input

1 3
1 4 7
3 6
4 1 8
6 8 10
1 5 2
2 7
10 4 1
10 2 3

Sample Output

7
8
zhx is naive!

题目分析:

有n道题,每道题i有做题时间ti,得到分数wi,以及这道题必须在li时间或之后完成,也就是说在做题i的时候,必须在li-ti时间或之后开始做。现在你只需要获得w分就够了,问你最快能在什么时候达到这个分数。

为了最快达到分数,那么我们做每道题i的时间就是在li-ti开始,在li做完。这就转化为一个01背包问题。对这些题目以开始时间从早到晚排序,如果相等就把题目分值大的放前面。计算出做所有题最长时间(也就是说在这个时间之外就不可能做完w分题目)maxt,从maxt开始倒序,将满足的更新dp数组(dp数组表示在i时间能达到最多的分数)。
最后遍历一遍dp数组,将满足w的最小序号输出。

代码如下:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>

using namespace std;

struct sa
{
    int t,v,l;
}a[35];

bool cmp(sa x, sa y)
{
    if (x.l-x.t!= y.l-y.t)
    return (x.l-x.t)<(y.l-y.t);
    return x.v>y.v;
}

int dp[100010];

int n,w;
int main()
{
    while(~scanf("%d%d",&n,&w))
    {
        int maxt=0,sum=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l);
            maxt=max(maxt,a[i].l);
            sum+=a[i].t;
        }
        maxt=max(sum,maxt);
        sort(a,a+n,cmp);
        memset(dp,0,sizeof(dp));
        for(int i=0; i<n; i++)
        {
            for(int j=maxt; j>=a[i].l; j--)
            {
                if (j>=a[i].t)
                {
                    dp[j]=max(dp[j-a[i].t]+a[i].v,dp[j]);
                }
            }
        }
        bool f=false;
        for(int i=0; i<=maxt; i++)
        {
            if (dp[i]>=w)
            {
                f=true;
                printf("%d\n",i);
                break;
            }
        }
        if (!f) printf("zhx is naive!\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值