• 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;
    } 
  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/13854238.html
Copyright © 2020-2023  润新知