zoukankan      html  css  js  c++  java
  • [CF1433F] Zero Remainder Sum

    Description

    给定一个大小为 (n imes m) 的矩阵,要求每行只能选取不超过一半的元素,使得所有选出元素的总和是 (k) 的倍数,且这个总和最大。求这个最大值。(n,m,k le 70)

    Solution

    考虑 dp,对于每一行 (i),首先预处理出 (f[i][j][l][res]) 表示在第 (i) 行中,从前 (j) 个数中选择了 (l) 个数,和 (mod k = res) 的最大和为多少。据此,我们可以对 (f[i][*][*][res])(max) 得到 (g[i][res]),即从第 (i) 行中选不超过一半的数,且满足总和 (mod k = res) 的限制条件时,能够达到的最大的和是多少。

    (h[i][res]) 表示考虑前 (i) 行,从里面选取若干个数(当然数量要合法),且满足总和 (mod k = res) 的限制条件时,能够达到的最大的和是多少。利用 (g[i][res]) 显然可以轻松计算。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define dbg(x) cout<<#x<<" = "<<x<<", "
    #define dbgn(x) cout<<#x<<" = "<<x<<endl
    
    const int N = 75;
    
    int a[N][N],n,m,k;
    int f[N][N][N][N],g[N][N],h[N][N];
    
    signed main()
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) 
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
            }
        }
        memset(f,-1,sizeof f);
        memset(g,-1,sizeof g);
        memset(h,-1,sizeof h);
        for(int i=1;i<=n;i++)
        {
            f[i][0][0][0]=0;
            for(int j=1;j<=m;j++)
            {
                for(int r=0;r<k;r++) f[i][j][0][r]=f[i][j-1][0][r];
                for(int l=1;l<=j;l++)
                {
                    for(int r=0;r<k;r++)
                    {
                        int pos=(r-a[i][j]+100*k)%k;
                        f[i][j][l][r]=f[i][j-1][l][r];
                        if(f[i][j-1][l-1][pos]!=-1)
                        {
                            f[i][j][l][r]=max(f[i][j][l][r],f[i][j-1][l-1][pos]+a[i][j]);
                        }
                    }
                }
            }
        }
    
        for(int i=1;i<=n;i++)
        {
            g[i][0]=0;
            for(int r=0;r<k;r++)
            {
                int ans=-1;
                for(int l=0;l<=m/2;l++)
                {
                    ans=max(ans,f[i][m][l][r]);
                }
                g[i][r]=ans;
            }
        }
        
    
        h[0][0]=0;
        for(int i=1;i<=n;i++)
        {
            for(int r=0;r<k;r++)
            {
                for(int d=0;d<k;d++)
                {
                    if(h[i-1][r]!=-1 && g[i][d]!=-1)
                    {
                        h[i][(r+d)%k]=max(h[i][(r+d)%k],h[i-1][r]+g[i][d]);
                    }
                }
            }
        }
    
        cout<<h[n][0]<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/mollnn/p/13878483.html
Copyright © 2011-2022 走看看