题干:

"无论何时何地,都会遵守约定"。"奋力逃吧"。"关于取下敌人性命这件事,也从不失约"。

小懒虫zmx平时最喜欢玩的游戏就是《王者荣耀》,在这款游戏中它也最喜欢百里守约这个英雄。最近,zmx准备冲国服百里,所以它开始练英雄,你有很多个时间段来练习英雄,每个时间段有一个开始时间点和结束时间点,以及可以获得的熟练度。不过现在你可以随意修改任意练习时间段的开始和结束时间点,但是你不能修改时间段的长度和获得的熟练度!由于要学习,你只能在固定时间段玩游戏,问你最多可以获得多少熟练度?

例如:你可以把[2,3),修改为[1,2)或者[3,4)等等,他们的长度都是1。

注意:对于某个时间段,不管你有没有修改,必须练完整个时间段长度才能获得熟练度!

输入描述:

第一行,三个整数n,S,T(0<n<=1000,0<S<T<1000)代表n个时间段和你能在[S,T)时间段内玩游戏。

接下来n行,每行三个整数a,b(0<a<b<1000),c(0<c<1e7),用空格分开,代表时间段起始时间[a,b)和可以获得的熟练度。

输出描述:

输出一行,包括一个整数,表示zmx能获得的最大熟练度。

示例1

输入

复制

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

输出

复制

6

示例2

输入

复制

5 1 5
1 2 1
2 3 2
1 3 3
3 4 2
3 6 4

输出

复制

7

解题报告:

可以看出,出这题的思路是,把数值加法看做区间的覆盖,于是背包问题就可以变形成一个区间问题了。

看出来之后就是一个裸的01背包,背包的大小为T-S。
第 i 个时间段可以看成一个物品,这个物品的体积w[i]=b[i]-a[i],价值v[i] 为熟练度c。
那么dp[i][j]就表示着在前 i 个时间段里花费 j 的时间练英雄能得到的最大熟练度。 

注意longlong,,2333

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
ll dp[2002];
int w[2002],v[2002];
int main()
{
	int n,s,t;
	cin>>n>>s>>t;
	int V = t-s;
	for(int x,y,c,i = 1; i<=n; i++) {
		cin>>x>>y>>c;
		w[i] = y-x;
		v[i] = c;
	}
	for(int i = 1; i<=n; i++) {
		for(int j = V; j>=w[i]; j--) {
			dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
		}
	}
	printf("%lld\n",dp[V]);
	return 0 ;
 }