原题链接
题目大意
有
n
n
n种干草,每种干草都有他们对应的价钱和质量。给出这
n
n
n种干草的价钱和质量,求出买够
m
m
m质量的干草至少需要多少钱。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
2 15
3 2
5 3
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
9
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
买
3
3
3个第
2
2
2种干草,重量为5*3=15
,价值为3*3=9
。
解题思路
如果求的是最大钱数,那么这题就是一个裸的完全背包,但是他求的是最小价值,所以要加一个初始化,把初始时所有的最小价格设成一个最大值,作者这里用的是
0
x
7
f
7
f
7
f
7
f
\mathbf{0x7f7f7f7f}
0x7f7f7f7f,然后把
d
p
0
dp_0
dp0设为
0
0
0,因为你不用取就可以达到
0
0
0个单位。
虽说初始化做好了,但是你加上初始化交上去,你肯定会
,因为有一些极端的数据就会卡死你,如下面的数据:
I
n
p
u
t
\mathbf{Input}
Input
3 100
100 1000
101 2000
1000 1
O u t p u t \mathbf{Output} Output
1
由于他有一个非常大的干草数,但是价格又非常便宜(是不是假的干草),你的程序就必须要选到他,即把容量放大,加一个额外的容量
e
x
t
r
a
extra
extra,我这里设他为
5001
5001
5001。
现在就可以放出状态转移方程了。
设
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种干草的价钱,而
e
x
t
r
a
extra
extra的定义如上。
d
p
j
=
{
d
p
j
1
≤
i
≤
n
,
0
≤
j
<
w
i
m
i
n
(
d
p
j
,
d
p
j
−
w
i
+
c
i
)
1
≤
i
≤
n
,
w
i
≤
j
≤
m
+
e
x
t
r
a
dp_j=\begin{cases} dp_j&1\le i\le n,0\le j<w_i \\min(dp_j,dp_{j-w_i}+c_i)&1\le i\le n,w_i\le j\le m+extra \end{cases}
dpj={dpjmin(dpj,dpj−wi+ci)1≤i≤n,0≤j<wi1≤i≤n,wi≤j≤m+extra
答案就是:
min
m
≤
i
≤
m
+
e
x
t
r
a
d
p
j
\min_{m\le i\le m+extra}dp_j
m≤i≤m+extramindpj
加上了
e
x
t
r
a
extra
extra交上去后,你就会
了。
上代码
#include<iostream>
#include<cstring>
using namespace std;
int n,m;
int w[1010],c[1010];
int dp[60000];
int main()
{
memset(dp,0x7f,sizeof(dp));
dp[0]=0;
int extra=5001;
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>w[i]>>c[i];
// for(int i=1; i<=m; i++) dp[1][i]=((i-1)/w[1]+1)*c[1];
for(int i=1; i<=n; i++)
{
for(int j=w[i]; j<=m+extra; j++)
{
dp[j]=std::min(dp[j],dp[j-w[i]]+c[i]);
}
}
int ans=0x7f7f7f80;
for(int i=m; i<=m+extra; i++) ans=std::min(ans,dp[i]);
cout<<ans<<endl;
return 0;
}
完美切题 ∼ \sim ∼