题解 | #小红取数#

小红取数

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

描述

给一个数组,要求从数组中选取一些数,使得这些数的和为kk的倍数且和最大

思路

  • 类似于背包的一个题,设dp[n][m]dp[n][m]表示考虑前nn个数,选取的数对kk取模为mm的最大价值
  • 转移方程为dp[n][m]=dp[n1][(ma[n])%k]+a[n]dp[n][m]=dp[n-1][(m-a[n])\%k]+a[n]
  • 采用滚动数组节省内存

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e3+5;
ll dp[2][MAXN];
ll a[MAXN];
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    int now=0,nxt=1;
    memset(dp[now],-1,sizeof(dp[now]));
    dp[now][0]=0;
    for(int i=1;i<=n;i++)
    {
        memcpy(dp[nxt],dp[now],sizeof(dp[now]));
        for(int j=0;j<k;j++)
            if(dp[now][j]>=0)
                dp[nxt][(j+a[i])%k]=max(dp[nxt][(j+a[i])%k],dp[now][j]+a[i]);
        now^=1;nxt^=1;
    }
    if(dp[now][0]!=0)
        printf("%lld\n",dp[now][0]);
    else
        puts("-1");
}

时间复杂度O(nk)O(nk),空间复杂度O(k)O(k)

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务