题目大意:
给你一个n*m的二维矩阵。你每一行不能选择超过
⌊
m
2
⌋
\lfloor\frac{m}{2}\rfloor
⌊2m⌋个数。问你能够选择出的最大的能够被
k
k
k整除的数字和.
n
,
m
,
k
≤
70
n,m,k \leq 70
n,m,k≤70
题目思路:
显然,每一行互相独立.所以可以分行dp. d p ( i , j , l ) dp(i,j,l) dp(i,j,l)代表前i个数,选择了j个数并且总和 m o d k = l mod\ k=l mod k=l的最大价值.直接子序列模型dp即可.
然后得到一个 r e s [ i ] [ j ] res[i][j] res[i][j]代表第i行,总和 m o d k = l mod\ k =l mod k=l的最大价值。每一行只能选择一个数,总共有n行。所以可以将其转换成分组背包,每组可不选的模型。再跑一遍背包dp即可。
然后这题有很多边界需要处理。
1.
r
e
s
res
res数组的初始值如何定:
r
e
s
[
i
]
[
0
]
=
0
res[i][0]=0
res[i][0]=0,其他的都等于-1代表不存在。
因为题目里说明了,每一行可以不选。所以
r
e
s
[
i
]
[
0
]
res[i][0]
res[i][0]需要赋值为0.
2. d p dp dp数组边界赋值为 -1.且 d p ( 0 , 0 , 0 ) = 0 dp(0,0,0)=0 dp(0,0,0)=0
3. f f f背包数组边界赋值为-1.且 f ( 0 , 0 ) = 0 f(0,0)=0 f(0,0)=0。因为 f f f的含义是“恰好”总和为k的概念。而不是最多。所以我们最开始的状态一定是要从 f ( 0 , 0 ) f(0,0) f(0,0)出发
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int maxn = 70 + 5;
int dp[maxn][maxn][maxn];
int res[maxn][maxn];
int a[maxn];
int f[maxn][maxn];
int main()
{
ios::sync_with_stdio(false);
int n , m , mod; cin >> n >> m >> mod;
memset(res , -1 , sizeof res);
for (int i = 1 ; i <= n ; i ++) res[i][0] = 0;
for (int t = 1 ; t <= n ; t++){
for (int i = 1 ; i <= m; i++) cin >> a[i];
memset(dp , -1 , sizeof dp);
dp[0][0][0] = 0;
for (int i = 1 ; i <= m ; i++){
dp[i][0][0] = 0;
for (int j = 1 ; j <= i ; j++){
for (int k = 0 ; k < mod ; k++){
if (dp[i - 1][j][k] != -1)
dp[i][j][k] = dp[i - 1][j][k];
if (dp[i - 1][j - 1][(k - a[i]%mod + mod)%mod] != -1)
dp[i][j][k] = max (dp[i][j][k] , dp[i - 1][j - 1][(k - a[i]%mod + mod)%mod] + a[i]);
}
}
}
for (int i = 1 ; i <= (m / 2) ; i++)
for (int j = 0 ; j < mod ; j++)
res[t][j] = max (res[t][j] , dp[m][i][j]);
}
memset(f , -1 , sizeof f);
for (int i = 0 ; i <= n ; i++) f[i][0] = 0;
for (int i = 1 ; i <= n ; i++)
for (int j = 0 ; j < mod ; j++)
for (int k = 0 ; k < mod ; k++)
if (f[i - 1][(j - k + mod)%mod] != -1 && res[i][k] != -1)
f[i][j] = max (f[i][j] , f[i - 1][(j - k + mod)%mod] + res[i][k]);
cout << f[n][0] << endl;
return 0;
}