【题目来源】
https://www.acwing.com/problem/content/5890/
【题目描述】
拼题A打卡奖励拼题 A 的教超搞打卡活动,指定了 N 张打卡卷,第 i 张打卡卷需要 mi 分钟做完,完成后可获得 ci 枚奖励的金币。
活动规定每张打卡卷最多只能做一次。
活动总时长为 M 分钟。
请你算出最多可以赢得多少枚金币?
【输入格式】
输入首先在第一行中给出两个正整数 N(≤10^3)和 M(≤365×24×60),分别对应打卡卷的数量和以“分钟”为单位的活动总时长(不超过一年)。
随后一行给出 N 张打卡卷要花费的时间 mi(≤ 600),最后一行给出 N 张打卡卷对应的奖励金币数量 ci(≤ 30)。
上述均为正整数,一行内的数字以空格分隔。
【输出格式】
在一行中输出最多可以赢得的金币数量。
【输入样例】
5 110
70 10 20 50 60
28 1 6 18 22
【输出样例】
40
【样例解释】
选择最后两张卷子,可以在 50+60=110 分钟内获得 18+22=40 枚金币。
【算法分析】
典型的 0-1 背包问题。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5, M=1e6+5;
int dp[M],val[N],vol[N];
int n,m,sum;
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>val[i];
for(int i=1; i<=n; i++) {
cin>>vol[i];
sum+=vol[i];
}
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(int i=1; i<=n; i++) {
for(int j=sum; j>=vol[i]; j--) {
dp[j]=min(dp[j],dp[j-vol[i]]+val[i]);
}
}
for(int i=sum; i>=0; i--) {
if(dp[i]<=m) {
cout<<i<<endl;
return 0;
}
}
return 0;
}
/*
in:
5 110
70 10 20 50 60
28 1 6 18 22
out:
40
*/
【参考文献】
https://tiku.scratchor.com/question/view/pdc5fqwzerntfda5
https://pintia.cn/problem-sets/994805046380707840/exam/problems/type/7
https://hexo.ab-in.cn/2022/04/18/GPLT2022-4-18-2/