题目如下:
思路 or 题解
D
P
[
i
]
[
j
]
[
0
/
1
]
DP[i][j][0/1]
DP[i][j][0/1]
在
前
i
个
数
字
中
选
择
,
和
为
j
在前\ i\ 个数字中选择,和为\ j
在前 i 个数字中选择,和为 j
0
表
示
i
这
个
数
字
不
选
,
1
表
示
i
这
个
数
字
被
选
0\ 表示\ i\ 这个数字不选, 1\ 表示\ i \ 这个数字被选
0 表示 i 这个数字不选,1 表示 i 这个数字被选
状态转移:
d
p
[
i
]
[
j
]
[
0
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
]
[
0
]
,
d
p
[
i
−
1
]
[
j
]
[
1
]
+
1
)
dp[i][j][0] = min(dp[i - 1][j][0], dp[i - 1][j][1] + 1)
dp[i][j][0]=min(dp[i−1][j][0],dp[i−1][j][1]+1)
d
p
[
i
]
[
j
]
[
1
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
−
s
[
i
]
]
[
0
]
,
d
p
[
i
−
1
]
[
j
−
s
[
i
]
]
[
1
]
)
(
j
−
s
[
i
]
>
=
0
)
dp[i][j][1] = min(dp[i - 1][j - s[i]][0], dp[i - 1][j - s[i]][1])\ \ \ (j - s[i] >= 0)
dp[i][j][1]=min(dp[i−1][j−s[i]][0],dp[i−1][j−s[i]][1]) (j−s[i]>=0)
初试状态定义:
d
p
[
0
]
[
0
]
[
1
]
=
0
dp[0][0][1] = 0
dp[0][0][1]=0
其余状态初试为:0x3f3f3f3f
AC代码:
int n, m, dp[N][N][2];
int s[N];
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> s[i];
memset(dp, 0x3f, sizeof dp);
dp[0][0][1] = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j <= m; j++)
{
if (j - s[i] >= 0)
dp[i][j][1] = min(dp[i - 1][j - s[i]][0], dp[i - 1][j - s[i]][1]);
dp[i][j][0] = min(dp[i - 1][j][0], dp[i - 1][j][1] + 1);
}
}
for (int i = 1; i <= m; i++)
{
int ans = min(dp[n][i][0], dp[n][i][1]);
if (ans == 0x3f3f3f3f) ans = -1;
cout << ans << '\n';
}
}
int main()
{
buff;
solve();
}