F. Zero Remainder Sum
题目链接
You are given a matrix aa of size n×mn×m consisting of integers.
You can choose no more than ⌊m2⌋⌊m2⌋ elements in each row. Your task is to choose these elements in such a way that their sum is divisible by kk and this sum is the maximum.
In other words, you can choose no more than a half (rounded down) of elements in each row, you have to find the maximum sum of these elements divisible by kk.
Note that you can choose zero elements (and the sum of such set is 00).
Input
The first line of the input contains three integers nn, mm and kk (1≤n,m,k≤701≤n,m,k≤70) — the number of rows in the matrix, the number of columns in the matrix and the value of kk. The next nn lines contain mm elements each, where the jj-th element of the ii-th row is ai,jai,j (1≤ai,j≤701≤ai,j≤70).
Output
Print one integer — the maximum sum divisible by kk you can obtain.
Examples
input
3 4 3
1 2 3 4
5 2 2 2
7 1 1 4
output
24
input
5 5 4
1 2 4 2 1
3 5 1 2 4
1 5 7 1 2
3 8 7 1 2
8 4 7 1 6
output
56
题意:
给定一个 n × m n \times m n×m 的矩阵,每行最多能取 $m / 2 $ (向下取整) 个数。
要求最后的和能整除 k k k,并且最大
思路:
d p dp dp 题, d p [ i ] [ j ] [ c ] [ d ] dp[i][j][c][d] dp[i][j][c][d] 表示选到第 i i i 行的第 j j j 个,这一行已经选了 c c c 个时,余数为 d d d 的最大值。
d p [ i ] [ j ] [ c ] [ d ] = m a x ( d p [ i ] [ j − 1 ] [ c ] [ d ] , m a x ( d p [ i ] [ j j ] [ c − 1 ] [ ( d − a [ i ] [ j ] + k ) % k ] ) + a [ i ] [ j ] ∣ c − 1 ≤ j j ≤ j − 1 ) dp[i][j][c][d] = max(dp[i][j - 1][c][d], max(dp[i][jj][c - 1][(d-a[i][j] + k) \% k]) + a[i][j] \ | \ c-1 \leq jj \leq j-1) dp[i][j][c][d]=max(dp[i][j−1][c][d],max(dp[i][jj][c−1][(d−a[i][j]+k)%k])+a[i][j] ∣ c−1≤jj≤j−1)
d p dp dp 数组初始都设置为 − 1 -1 −1, d p [ 1 ] [ 0 ] [ 0 ] [ 0 ] dp[1][0][0][0] dp[1][0][0][0] 设置为 0 0 0 。
每一行
d
p
dp
dp 完后,要对下一行的
d
p
[
i
+
1
]
[
0
]
[
0
]
[
d
]
dp[i + 1][0][0][d]
dp[i+1][0][0][d] 赋值 这里很关键,自己做的时候初始状态一直设置不好
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include <time.h>
//srand((unsigned)time(NULL));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int N = 1e4 + 10;
int n, m, k;
int a[100][100];
int dp[73][73][40][72];
int v[73];
int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d" , &a[i][j]);
memset(dp, -1, sizeof(dp));
memset(v, -1, sizeof(v));
int down = m / 2;
dp[1][0][0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int c = 0; c <= down; c++) {
for (int md = 0; md < k; md++) {
int yu = (md - a[i][j] + 100 * k) % k;
dp[i][j][c][md] = max(dp[i][j - 1][c][md], dp[i][j][c][md]);
v[md] = max(v[md], dp[i][j][c][md]);
for (int jj = c - 1; jj < j; jj++) {
if (dp[i][jj][c - 1][yu] == -1) continue;
dp[i][j][c][md] = max(dp[i][jj][c - 1][yu] + a[i][j], dp[i][j][c][md]);
v[md] = max(v[md], dp[i][j][c][md]);
}
}
// for (int md = 0; md < k; md++) {
// dp[i + 1][0][0][md] = max(dp[i + 1][0][0][md], dp[i][j][c][md]);
// }
}
}
for (int x = 0; x < k; x++) {
dp[i + 1][0][0][x] = v[x];
v[x] = -1;
}
}
printf("%d\n", max(0, dp[n + 1][0][0][0]));
return 0;
}
/*
4 2 49
16 42
58 37
2 17
40 61
*/