[acwing]1047.糖果
/*
dp[i][j] 表示只考虑前 i 件物品,模 k 余 j 的最大价值
如果不取第 i 件物品,dp[i][j] = dp[i - 1][j]
如果取第 i 件物品,dp[i][j] = dp[i - 1][((j - v[i]) % k + k) % k] + v[i]
遍历顺序 i[1, n],j[0, k - 1]
无需初始化
dp[n][0]
*/
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 110;
int n, k;
int v[N];
int dp[N][N];
int main()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
for (int i = 1; i <= n; i++)
for (int j = 0; j <= k - 1; j++) {
dp[i][j] = dp[i - 1][j]; // 不取第 i 个物品
if (dp[i - 1][((j - v[i]) % k + k) % k] != 0) // 取第 i 个物品,看之前有没有值与 v[i] 相加模 k 等于 j
dp[i][j] = max(dp[i - 1][j], dp[i - 1][((j - v[i]) % k + k) % k] + v[i]);
else if (v[i] % k == j) // 如果找不到,说明不能在原来的基础上进一步增大,再判断只有 v[i] 自身能否满足模 k 等于 j
dp[i][j] += v[i];
}
printf("%d", dp[n][0]);
return 0;
}
标签:件物品,变种,int,01,include,背包,dp
From: https://www.cnblogs.com/cong0221/p/17170336.html