有
n
n
n中大小不同的数字
a
i
a_i
ai,每种数字
m
i
m_i
mi,判断是否可以从这些数字之中选出若干使它们的和恰好为
K
K
K。
限制条件:
1
≤
n
≤
100
1≤n≤100
1≤n≤100
1
≤
a
i
,
m
i
≤
100000
1≤a_i,m_i≤100000
1≤ai,mi≤100000
1
≤
K
≤
100000
1≤K≤100000
1≤K≤100000
题解:
一般动态规划:
步骤:
dp数组含义:
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]=用前
i
i
i种数字是否能拼成
j
j
j
初始条件:
d
p
[
0
]
[
1
−
K
]
=
F
a
l
s
e
;
d
p
[
0
−
n
]
[
0
]
=
T
u
r
e
dp[0][1-K]=False; dp[0-n][0]=Ture
dp[0][1−K]=False;dp[0−n][0]=Ture
递推公式:
d
p
[
i
]
[
j
]
=
{
∃
d
p
[
i
−
1
]
[
j
−
k
×
a
i
]
为
真
∣
0
≤
k
≤
m
i
&
k
×
a
i
≤
j
}
dp[i][j]=\{∃ dp[i-1][j-k×a_i ]为真|0≤k≤m_i \& k×a_i≤j\}
dp[i][j]={∃dp[i−1][j−k×ai]为真∣0≤k≤mi&k×ai≤j}
递推方向:从上向下
结果:
d
p
[
n
]
[
K
]
dp[n][K]
dp[n][K]是否为真
时间复杂度 :
O
(
K
∑
i
m
i
)
O(K∑_im_i )
O(K∑imi)
代码 :函数
s
o
l
v
e
1
(
)
solve1()
solve1()
优化动态规划:
上面的动态规划的优化方向:
第一: dp数组中只存取bool型结果会有不少浪费,可以用来存取更有效的信息
第二:我们递推只使用用了从上到下的递推方向,我们可能可以使用左到右的递推方向来辅助
步骤:
dp数组含义:
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]=用前
i
i
i种数字是拼成
j
j
j,第i种数字最多剩余多少个,如果拼不成j就令其为-1
初始条件:
d
p
[
0
]
[
1
−
K
]
=
−
1
;
d
p
[
0
]
[
0
]
=
0
,
d
p
[
1
−
n
]
[
0
]
=
m
i
dp[0][1-K]=-1; dp[0][0]=0,dp[1-n][0]=m_i
dp[0][1−K]=−1;dp[0][0]=0,dp[1−n][0]=mi
递推公式:
d
p
[
i
]
[
j
]
=
{
m
i
d
p
[
i
−
1
]
[
j
]
≥
0
−
1
j
<
a
i
o
r
d
p
[
i
]
[
j
−
a
i
]
≤
0
d
p
[
i
]
[
j
−
a
i
]
−
1
其
他
dp[i][j]=\begin{cases} m_i & dp[i-1][j]≥0 \\ -1 &j<a_i or dp[i][j-a_i ]≤0\\ dp[i][j-a_i ]-1 &其他\\\end{cases}
dp[i][j]=⎩⎪⎨⎪⎧mi−1dp[i][j−ai]−1dp[i−1][j]≥0j<aiordp[i][j−ai]≤0其他