F - Zero Remainder Sum - 四维动态规划

F - Zero Remainder Sum

题意:

给你n行每行m个元素 每行可以选择不超过(m/2) 个元素 最后将选择的元素 加到一起 余数为零的最大和

思路:

四维dp dp[i][j][w][u] 代表 第i行 到第j个元素 已经选了w个元素 余数为u 的最大和  

第j个数 由第j-1个数转移过来 每次转移 w值也相应变化 类似01背包 取与不取 这题要多一个余数处理(而余数也恰恰是核心) 每次取了余数就会改变(u + a[i][j])%k  对于每个余数 更新当前状态最大值 

然后还要加一个处理 因为有i行 前一行的相应余数时的最大值 应该转移给下一行 用dp[i + 1][0][0][ii] = max(dp[i][j][w][ii], dp[i + 1][0][0][ii]);

复制代码
#include <bits/stdc++.h> 
#define ll long long
#define pi acos(-1)
#define F ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int  n, m, k, dp[80][80][80][80], a[80][80];//不用开ll 否则会MLE 

int main()
{
    F; 
    cin >> n >> m >> k;
    memset(dp, -1, sizeof(dp));//开始赋值为-1 表示没更新过  
    dp[1][0][0][0] = 0;//起始转移点必须为0 
    for(ll i = 1; i <= n; i++){
        for(ll j = 1; j <= m; j++){
            cin >> a[i][j];
        }
    } 
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            //min(j, m/2)的处理是因为 才选到第j个元素所以已选元素不可能比j大 且题目要求每行选择的元素 小于m/2 
            for(int w = 0; w <= min(j, m / 2); w++){
                for(int u = 0; u < k; u++){
                    //有循环 dp[i][j][w][u]的值改变 要用max 若果是一次直接等于dp[i][j-1][w][u]也可 
                    dp[i][j][w][u] = max(dp[i][j - 1][w][u], dp[i][j][w][u]);
                    //w不能是0 应为w-1就会变成负数 没意义 要判断前一个有没有被更新过 
                    //如果没被更新过说明之前不存在那样的余数的情况就不能往下更新 
                    if(w && dp[i][j - 1][w - 1][u] != -1)//往下更新 
                    dp[i][j][w][(u + a[i][j]) % k] = max(dp[i][j][w][(u + a[i][j]) % k], dp[i][j - 1][w - 1][u] + a[i][j]);
                }
                for(int ii = 0; ii < k; ii++){//第一层取相应余数时的最大值转移给下一层 
                    //对于不同的k都可能为最大所以放到这 且用max 
                    dp[i + 1][0][0][ii] = max(dp[i][j][w][ii], dp[i + 1][0][0][ii]);
                }
            } 
        }
    }
    //最后前n+1行 第0个元素 该行选择0个数 余数为0的最大值就是 答案值  
    cout << dp[n + 1][0][0][0] << endl;
    return 0;
}
复制代码

 

 

posted @   Yaqu  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
点击右上角即可分享
微信分享提示