题目链接:
https://www.acwing.com/problem/content/1049/
题目大意:
\(n\) 个数字,可以选择其中的若干个,要求它们的和是 \(k\) 的倍数,求最大的和为多少
思路:
因为每选择一个物品的状态可以由上一个状态转移过来,于是想到 \(dp\),就是一个 01 背包,我们将一个物品放入背包中,最后背包的容量为 \(k\) 的倍数,数字 * k 之后很大,但是某个数字对结果有影响的部分只有它 /\(k\) 之后的余数,于是想到 取模。
\(dp[i][j]\) 中的 \(i\) 为第 \(i\) 件物品,\(j\) 为对 \(k\) 取模后的结果,写出 01背包。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int w, n, k, dp[N][N];
int main(){
cin >> n >> k;
for (int i = 0; i <= n; i++)
for (int j = 0; j < k; j++)
dp[i][j] = INT_MIN;
dp[0][0] = 0; //不放数的时候结果为 0
for (int i = 1; i <= n; i++){
scanf("%d", &w);
for (int j = 0; j <= k - 1; j++)
dp[i][j] = max(dp[i - 1][j], dp[i - 1][((j - w) % k + k) % k] + w);
}
cout << dp[n][0] << "\n";
return 0;
}