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!
题目分析
看了下,和有一道救火的题很像(点击查看),都是有了限制条件的01背包问题,顺着这个题也一样的想法,对 l 排序后,觉得应该没问题的,结果肯定是 WA 了(启迪:没有完全一样的题目QAQ),之后手动推了一下dp数组
样例:
2 3
5 2 6
2 2 4
手动算一下都知道答案应该是8,但是对 l 排序的程序输出的答案是9,我们在第6s完成第一个题目,随后用2s完成第二个任务,用时8s,而如果按照对 l 排序的话,我们先在第4s完成第二个题目,在用5s完成第一个题目,用时9s,这就明显不对了,为什么会出现这个问题呢?
注意到我们对 l 排序的时候,在dp[6] = 0 ,表示之前没有数据可以转移至此,但实际上,当我们先更新第一个题目的时候,dp[6] = 2,这个状态是可以转移得到的,这就是问题所在了,我们对题目排序,其目的就是为了使得先处理的题目不受后处理的任务影响,而我们对 l 排序的时候就出现了后处理的题目可以影响先处理的题目的情况
而按照某一题目最早开始时间排序,这样在更新某个题目的时候从最早开始的题目开始,可以使得先处理的任务不受后处理的任务影响,因此,我们按照某一个题目最早可开始时间排序,就可以解决这个问题了。
代码区
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<cmath>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#define bug printf("**********\n");
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const ll inf = 1e18 + 5;
const int mod = 1e8;
const int Max = 3e6 + 10;
struct Node
{
int t, l;
ll v;
}node[Max];
bool cmp(const Node& node1, const Node& node2)
{
return node1.l < node2.l;
//按照某一题目最早开始时间排序,这样在更新某个题目的时候从最早开始的题目开始,使得先处理的任务不受后处理的任务影响
}
int n;
ll dp[Max], w;
int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
while (scanf("%d%lld", &n, &w) != EOF)
{
int m = 0;//记录最晚完成时间
int end = 0;
memset(dp, 0, sizeof(dp));
for (int i = 1;i <= n;i++)
{
scanf("%d%lld%d", &node[i].t, &node[i].v, &node[i].l);
m += node[i].t;
end = max(end, node[i].l);
}
m += end; //总时间加上最晚视为作弊时间,就是最晚完成时间
sort(node + 1, node + 1 + n, cmp);
for (int i = 1;i <= n;i++)
{
for (int j = m; j >= node[i].l && j >= node[i].t;j--) //当前的时间必须大于判定作弊事件,而且转移前的时间必须大于t
{
dp[j] = max(dp[j], dp[j - node[i].t] + node[i].v);
}
}
bool ok = false;
int i;
for (i = 1; i <= m;i++) //找到最早的完成时间
{
if (dp[i] >= w)
{
ok = true;
break;
}
}
if (ok)
printf("%d\n", i);
else
printf("zhx is naive!\n");
}
return 0;
}