题解:CF1866D Digital Wallet
一:思路
求最大值,可以考虑dp,结果发现每次考虑时,只需考虑一个 n 行 k 列的矩阵,在这之间选数,所以维护这样一个矩阵来 dp 即可。
同时创建x和y两个数组;
x[n * i+j]:数组中第 i 行第 j 列为止的最大答案。
y[n * i+j]:数组中选上第 i 行第 j 列的最大答案。
然后输出x[n * k];
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=20,M=1e5+5;
ll a[M*N],x[105],y[105];
ll n,m,k;
int main(){scanf("%lld%lld%lld",&n,&m,&k);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%lld",&a[n*j+i]);}}for(int i=1;i<=m-k+1;i++){for(int j=1;j<=n*k;j++){y[j]=x[min(j+n-1,n*k)]+a[j+n*i];}for(int j=1;j<=n*k;j++){x[j]=y[j];}for(int j=2;j<=n*k;j++){x[j]=max(x[j],x[j-1]);}}printf("%lld",x[n*k]);
}
/*
3 3 1
10 4 2
8 1 9
4 8 2
*/