Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 8958 Accepted Submission(s): 3766
Problem Description
Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more.
The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi.
If he had M units of money, what’s the maximum value iSea could get?
Input
There are several test cases in the input.
Each test case begin with two integers N, M (1 ≤ N ≤ 500, 1 ≤ M ≤ 5000), indicating the items’ number and the initial money.
Then N lines follow, each line contains three numbers Pi, Qi and Vi (1 ≤ Pi ≤ Qi ≤ 100, 1 ≤ Vi ≤ 1000), their meaning is in the description.
The input terminates by end of file marker.
Output
For each test case, output one integer, indicating maximum value iSea could get.
Sample Input
2 10
10 15 10
5 10 5
3 10
5 10 5
3 5 6
2 7 3
Sample Output
5
11
问题连接
有N个商人卖货物,每个商人只卖一件货物,货物的价格为p,价值为v,但是这里的商人比较自负,如果你手头没有q那么他会拒绝和你交易。有M的货币,问能获得的最大价值是多少。
每件货物要么拿要么不拿,所以是01背包。但是要预先处理一下数据,因为可能出现这种情况:有M的钱,可以先买商人i的货物(相关参数为Pi,Qi,Vi),再买商人j的货物(Pj,Qj,Vj),而如果先买j的货物就买不了i的货物,如果有这种情况且j放在i的前面,那么就会出错,这种就是有后效性的,要消除后效性才能使用动态规划。
对于上面的情况不难列出:
M>=Qi , M-Pi>=Qj , M>=Qj , M-Pj
Pi-M<=-Qj , M-Pj
也就是说当Qi-Pi>Qj-Pj时就可能会有上面的情况,这时应该先买i再卖j,又01背包的拿货物的顺序是先空出空间再看是否更新,也就是说是先拿当前的货物再按之前的DP结果拿货物,所以,在排序的时候应该让i在j的后面。
#include
#include
#include
#include
using namespace std;
const int N=505;
const int M=5005;
int dp[M];
struct group{
int p,q,v,gap;
}item[N];
bool cmp(group&obj1,group&obj2){
return obj1.gap<obj2.gap;
}
int main(){
int n,m,i,j;
while(scanf("%d %d",&n,&m)!=EOF){
for(i=0;i<n;i++){
scanf("%d %d %d",&item[i].p,&item[i].q,&item[i].v);
item[i].gap=item[i].q-item[i].p;//记录差值,减少减法运算次数
}
sort(item,item+n,cmp);//排序
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++){//01背包
for(j=m;j>=item[i].q;j--){
if(dp[j]<dp[j-item[i].p]+item[i].v){
dp[j]=dp[j-item[i].p]+item[i].v;
}
}
}
printf("%d\n",dp[m]);
}
return 0;
}