题解:CF1866D Digital Wallet

· · 题解

传送门

题意

给你一个 n \times m 的矩阵,让你从 1k 列,2k+1 列,3k+2 列…… m-k+1m 列中各选一个数(不可以重复选择),要你求出这些选出来的数的最大值。

思路

动态规划。

第一维枚举这是第几列,第二维枚举目前这一列中的第几个数,第三维枚举之前已选择的数的个数。

因为每一列最多可以被选择 k 次,为了保证此列在可选择的范围内,每一次选数时的起点必须大于等于 i-k+1 列,所以只需从 i-k+1 找到 i 即可,由于本蒟蒻是枚举的选择这个数前的选择数目,所以是 从 i-ki-1

为了保证每个数只选择一次,要从后往前找,有点类似背包的思想。

状态转移方程:dp_{p+1} = \max(dp_{p}+a_{j,i},dp_{p+1})

其中,p 指之前已选择的数的数量,a_{j,i} 表示矩阵中第 j 行,第 i 列的数,时间复杂度为 O(mnk)

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k,dp[100005]={0},a[15][100005],o=0;
signed main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int p=i-1;p>=max(i-k,o);p--)
            {
                dp[p+1]=max(dp[p]+a[j][i],dp[p+1]);
            }
        }
    }
    cout<<dp[m-k+1];
    return 0;
}