引言
题目链接:https://www.acwing.com/problem/content/description/1049/
思路
状态表示:
dp[i][j]:表示从前 i 个数中组成总和 %k 等于 j 的方案数。
状态转移:
可以根据是否选择第 i 个数来进行划分:
-
包含第 i 个数:
dp[i - 1][((j - w[i]) % k + k) % k] + w[i]
-
不包含第 i 个数:
dp[i - 1][j]
转移方程证明:
首先不包含第 i 个数的转移方程比较容易看出,不包含 i 的方案数和从前 i-1 个数中组成总和 %k 等于 j 的方案数相同。
包含第 i 个数的转移方程,可以设前 i-1 个数的和为 S,其中有 (S + w[i]) % k = j,那么 S = nk + j - w[i],则 S % k = (j - w[i]) % k。
注意: j - w[i] 可能为负数,所以要 + k
代码
#include <bits/stdc++.h>
#define N 1000
int n,k;
int w[N];
int dp[N][N];
int main() {
std::cin >> n >> k;
for (int i = 1 ; i <= n ; i ++ ) std::cin >> w[i];
memset(dp,-0x3f,sizeof dp);
dp[0][0] = 0;
for (int i = 1 ; i <= n ; i ++ ) {
for (int j = 0 ; j <= k - 1 ; j ++ ) {
dp[i][j] = std::max(dp[i-1][j],dp[i-1][((j - w[i]) % k + k) % k] + w[i]);
}
}
std::cout << dp[n][0] << '\n';
return 0;
}
标签:方程,包含,int,个数,糖果,转移,dp
From: https://www.cnblogs.com/NachoNeko/p/18004753