zoukankan      html  css  js  c++  java
  • Codeforces-1433F-Zero Remainder Sum

    Zero Remainder Sum

    题目链接

    ^-^

    题目大意

    相信看题解的都是看懂题目的(主要是懒得打字了

    解题思路

    一看就是dp题,我们按照一行一行从上到下、从左到右的顺序来求解、我们用dp[i][j][cnt][rem] 表示选到第i行、第j列并且第i行已经选择cnt个元素且余数为rem的时候的最大值。那么现要进行初始化,dp[0][0][0][0]=0,其余的都是-inf

    然后就是递归式

    对于每一行的每一列的元素假设为a[i][j]来说,都有选择(前题是cnt+1<=m/2)或者不选的可能。如果选择这个的话,就向后更新,即

        nrem=(rem+a[i][j])%k;
        dp[i][j+1][cnt+1][nrem]=max(dp[i][j+1][cnt+1][nrem],dp[i][j][cnt][rem]+a[i][j]);

    如果不选择的话,就有

        dp[i][j+1][cnt][nrem]=max(dp[i][j+1][cnt][nrem],dp[i][j][cnt][rem]+a[i][j]);

    但是当我们遍历到最后一个元素的时候,就有些不同,因为我们第i行的答案受第i-1行的影响(从上到下),因此我们遍历到每一行的最后一个元素的时候,要将其更新到下一行而不是再外后,除此之外,如果这个值选取的话,对下行的cnt值并没有影响,因此也就不用进行cnt+1次操作。最后的答案就是dp[n][0][0][0]

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=70;
    int dp[maxn][maxn][maxn][maxn];
    int a[maxn][maxn];
    const int inf=-0x3f3f3f;
    int main()
    {
        int n,m,k;
        cin>>n>>m>>k;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                cin>>a[i][j];
            }
        }
        for(int i=0;i<maxn;i++)
        {
            for(int j=0;j<maxn;j++)
            {
                for(int cnt=0;cnt<maxn;cnt++)
                {
                    for(int rem=0;rem<maxn;rem++)
                    {
                        dp[i][j][cnt][rem]=inf;
                    }
                }
            }
        }
        dp[0][0][0][0]=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                for(int cnt=0;cnt<m/2+1;cnt++)
                {
                    for(int rem=0;rem<k;rem++)
                    {
                        if(dp[i][j][cnt][rem]==-inf) continue;
                        int ni=(j==m-1?i+1:i);
                        int nj=(j==m-1?0:j+1);
                        if(i!=ni) //显示不选择的情况 表示切换到下一行 
                        {
                            dp[ni][nj][0][rem]=max(dp[ni][nj][0][rem],dp[i][j][cnt][rem]); 
                        } 
                        else{
                            dp[ni][nj][cnt][rem]=max(dp[ni][nj][cnt][rem],dp[i][j][cnt][rem]); 
                        }
                        if(cnt+1<=m/2)
                        {
                            int nrem=(a[i][j]+rem)%k;
                            if(i!=ni)
                            {
                                dp[ni][nj][0][nrem]=max(dp[ni][nj][0][nrem],dp[i][j][cnt][rem]+a[i][j]);
                            }
                            else{
                                dp[ni][nj][cnt+1][nrem]=max(dp[ni][nj][cnt+1][nrem],dp[i][j][cnt][rem]+a[i][j]);
                            }
                        }
                    }
                }
            }
        }
        cout<<dp[n][0][0][0]<<endl;
        return 0;
    } 
  • 相关阅读:
    路径操作OS模块和Path类(全)一篇够用!
    数据可视化:绘图库-Matplotlib
    matplotlib中文显示的问题
    Microsoft Visual C++ 14.0 is required问题解决
    python习题——随机整数生成类
    python——时间模块
    怎么获取10个线程的结果再返回
    集群服务器定时任务,只运行一个定时器的设计
    分布式事务
    分布式数据库---分库分表
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/13854238.html
Copyright © 2011-2022 走看看