F. Zero Remainder Sum (dp)

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][j1][c][d],max(dp[i][jj][c1][(da[i][j]+k)%k])+a[i][j]  c1jjj1)

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
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值