1 条题解

  • 1
    @ 2026-9-27 17:40:46

    老师的正解是错的,时间复杂度是O(NNM)最大是5*10^8

    我的新的题解优化了一下将一个N优化成了K O(NMK)最大为2.5*10^7主要使用了一个类似前缀dp的高级做法,只能说老师还是太菜了,菜就要多练建议拜我为师

    这个数据用时我100ms 老师600ms 但是数据有点水 其实是能卡掉老师的代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define lowbit(x) x&-x
    #define ull unsigned long long
    #define ls(x) x<<1
    #define rs(x) x<<1|1
    const int INF = 0x3f3f3f3f3f3f3f3f;
    const int N = 1e3+10;
    const int M = 1e5 + 10;
    const int K = 1e5 + 10;
    const int mod = 10007;
    const int base = 998244353;
    int n,m,k;
    int a[N][N];
    int pre[N][N];
    int sum[N][N];
    int sum1[N][N];
    int dp[N][N];
    int ans;
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0);
    	cout.tie(0);
    	freopen("shop.in","r",stdin);
    	freopen("shop.out","w",stdout);
    	cin>>n>>m>>k;
    	for(int i=1;i<=m;i++){
    		for(int j=1;j<=n;j++){
    			cin>>a[i][j];
    			pre[i][j]=pre[i][j-1]+a[i][j];
    		}
    	}
    	for(int j=1;j+k-1<=n;j++){
    		dp[1][j]=pre[1][j+k-1]-pre[1][j-1];
    	}
    	for(int j=1;j+k-1<=n;j++){
    		sum[1][j]=max(sum[1][j-1],dp[1][j]+pre[2][j+k-1]-pre[2][j-1]);//前缀dp
    	}
    	for(int j=n-k+1;j>=1;j--){
    		sum1[1][j]=max(sum1[1][j+1],dp[1][j]+pre[2][j+k-1]-pre[2][j-1]);//后缀dp
    	}
    	for(int i=2;i<=m;i++){
    		for(int j=1;j+k-1<=n;j++){
    			if(j-k>=1){
    				dp[i][j]=max(sum[i-1][j-k]+pre[i][j+k-1]-pre[i][j-1],dp[i][j]);
    			}
    			for(int s=max(1ll,j-k+1);s<=min(n-k+1,j+k-1);s++){
    				dp[i][j]=max(dp[i][j],dp[i-1][s]+pre[i][s+k-1]-pre[i][s-1]+pre[i][j+k-1]-pre[i][j-1]-(pre[i][min(s+k-1,j+k-1)]-pre[i][max(s,j)-1]));
    			}
    			if(j+k<=n-k+1){
    				dp[i][j]=max(dp[i][j],sum1[i-1][j+k]+pre[i][j+k-1]-pre[i][j-1]);
    			}
    			sum[i][j]=max(sum[i][j-1],dp[i][j]+pre[i+1][j+k-1]-pre[i+1][j-1]);//前缀dp
    		}
    		for(int j=n-k+1;j>=1;j--){
    			sum1[i][j]=max(sum1[i][j+1],dp[i][j]+pre[i+1][j+k-1]-pre[i+1][j-1]);//后缀dp
    		}
    	}
    	for(int i=1;i<=n-k+1;i++){
    		ans=max(ans,dp[m][i]);
    	}
    	cout<<ans;
    	return 0;
    }
    /*
    显然这是一个dp
    我们定义dp[i][j]表示第i天,补货的是从j开始j+k-1结束能赚到的东西的
    */
    

    信息

    ID
    3700
    时间
    1000ms
    内存
    512MiB
    难度
    未评定
    标签
    递交数
    21
    通过
    5
    上传者