原题链接
题目大意
有
n
n
n类题目,每一类题目有切掉他所需的时间和切掉他可以得到的分数,每一类题目都有无限多个,现在给你有限的时间,求出在有限的时间内你可以得到最多多少分。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
300 4
100 60
250 120
120 100
35 20
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
605
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
做
2
2
2种第二类题目和
3
3
3种第四类题目,总时间120*2+20*3=300,可得分数250*2+35*3=605分。
解题思路
本题为完全背包,从
1
∼
m
1\sim m
1∼m循环遍历时间,如果够做某一道题就比较一下做与不做的价值即可。
设
d
p
j
dp_j
dpj为用时间
j
j
j可以做的最大分数,
w
i
w_i
wi是第
i
i
i类题的所需时间,
c
i
c_i
ci为第
i
i
i类题的分数,则:
d
p
j
=
{
0
j
=
0
m
a
x
(
d
p
j
,
d
p
j
−
w
i
+
c
i
)
1
≤
i
≤
n
,
w
i
≤
j
≤
m
dp_{j}=\begin{cases} 0&j=0 \\max(dp_{j},dp_{j-w_i}+c_i)&1\le i\le n,w_i\le j\le m \end{cases}
dpj={0max(dpj,dpj−wi+ci)j=01≤i≤n,wi≤j≤m
答案就是:
d
p
m
dp_m
dpm
上代码
#include<iostream>
using namespace std;
int n,m;
int w[10010],c[10010];
int dp[20010];
int main()
{
cin>>m>>n;
for(int i=1; i<=n; i++) cin>>c[i]>>w[i];
for(int i=1; i<=n; i++)
{
for(int j=w[i]; j<=m; j++)
{
dp[j]=std::max(dp[j],dp[j-w[i]]+c[i]);
}
}
cout<<dp[m]<<endl;
return 0;
}
完美切题 ∼ \sim ∼
该博客讨论了一种常见的计算机科学竞赛问题——完全背包问题。博主解释了问题背景,即在有限时间内最大化得分,通过列举样例展示了问题的具体实例。接着,博主详细介绍了解题思路,将问题归类为完全背包问题,并给出了采用动态规划的解决方案。代码部分展示了一个C++实现,用于求解在给定时间内能获得的最大分数。
379





