MYF

HDU 5410 CRB and String

题目链接

HDU 5410

〇一背包+完全背包

题目分析

题目大意

一个人有m元钱,有n件商品,告诉你每一件商品的价格w,以及a, b,如果购买x件该商品,则可以得到a * x + b颗糖,问,这个人最多能得到多少颗糖?

解析

赛后看题解之后发现是〇一背包+完全背包,总觉得这个想法有问题,万一你〇一背包的时候没有取这件商品,完全背包的时候却要了,那这个方法不就错了么?

可以这样证明这个方法的正确性:如果你〇一背包的时候都不要,那么跑完全背包的时候更不要这个东西了

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <deque>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define IN freopen("input.txt","r",stdin);
#define OUT freopen("output.txt","w",stdout);
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
const int maxn=1000000+5;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
int dp[2005];
int main() {
int t,n,m,w,a,b;
scanf("%d",&t);
while (t--) {
Memset(dp, 0);
scanf("%d%d",&m,&n);

for (int i=1; i<=n; i++) {
scanf("%d%d%d",&w,&a,&b);

for (int i=m; i>=w; i--)
dp[i]=max(dp[i], dp[i-w]+a+b);

for (int i=w; i<=m; i++)
dp[i]=max(dp[i], dp[i-w]+a);
}

printf("%d\n",dp[m]);
}
return 0;
}