题解 | #小红取数#

小红取数

http://www.nowcoder.com/practice/6a7b2b6c9e3a4f56b1db9f8ca08d889b

小红取数

难度:3星

首先第一个想法是,开一个dp数组,dp[i]dp[i] 代表取前i个数的最大值。

那么dp[i]怎么求呢?很明显,如果要取了第 ii 个数 a[i]a[i] ,满足和能被k整除,那么就有个限制:前i-1个数里,满足取的数之和除以k的余数为 ka[i]k-a[i] ,之后加上 a[i]a[i] 才能正好被k整除。

所以一维数组是不够的,需要开二维数组:dp[i][j]dp[i][j] 代表前 ii 个数里面,取一些数,相加的和除以 kk 的余数为 jj 的最大值。

这样就得到转移方程:

dp[i][(j+a[i])%k]=max(dp[i1][j]+a[i],dp[i1][(j+a[i])%k])dp[i][(j+a[i])\%k]=max(dp[i-1][j]+a[i],dp[i-1][(j+a[i])\%k])

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100100];
ll dp[1010][1010];
int main(){
    long long n,k,i,j;
    cin>>n>>k;
    for(i=1;i<=n;i++)cin>>a[i];
    for(i=0;i<=n;i++){
        for(j=0;j<k;j++){
            dp[i][j]=-1e18;
        }
    }
    dp[0][0]=0;

    for(i=1;i<=n;i++){
        for(j=0;j<k;j++){
            dp[i][(j+a[i])%k]=max(dp[i-1][j]+a[i],dp[i-1][(j+a[i])%k]);
        }
    }
    if(dp[n][0]<=0)cout<<-1;
    else cout<<dp[n][0];
}

全部评论
请大佬帮忙看下,同样思路写出来的程序,为什么我的会出现dp[n-1][0]%k!=0的情况。 #include <iostream> #include <vector> using namespace std; int main(){ int n, k; cin >> n >> k; vector<long long=""> arr(n, 0); vector<long long=""> temp(k, 0); vector<vector><long long="">> sum(n, temp); for(int i = 0;i < n;i++){ cin >> arr.at(i); } for(int i = 0;i < n;i++){ if(i == 0){ sum.at(0).at(arr.at(0) % k) = arr.at(0); continue; } for(int j = 0;j < k;j++){ sum.at(i).at((j + arr.at(i)) % k) = max(sum.at(i - 1).at(j) + arr.at(i), sum.at(i - 1).at((j + arr.at(i)) % k)); } } if(sum.at(n - 1).at(0) <= 0){ cout << -1; } else{ cout << sum.at(n - 1).at(0); } return 0; }</long></vector></long></long></vector></iostream>
点赞 回复 分享
发布于 2021-10-29 16:07

相关推荐

06-04 09:27
门头沟学院 Java
点赞 评论 收藏
分享
评论
4
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务