P14300 [JOI2023 预选赛 R2] 货物列车 / Freight Train

#include<bits/stdc++.h>
using namespace std;
const int N=460;
int n,w,d,ans,dp[2][N][N*N],a[N]; // dp使用滚动数组优化空间

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>w>>d;
    for(int i=2;i<=n;i++)cin>>a[i]; // 读入每个车站的货物价值
    
    // 检查是否可以直接运输所有货物
    int x=0,p=n;
    while(p>1)x+=(p-1)*2,p-=w; // 计算最小所需距离
    if(x<=d){ // 如果距离足够运输所有货物
        for(int i=2;i<=n;i++)
            ans+=a[i]; // 直接累加所有货物价值
        cout<<ans;
        return 0;
    }
    
#define u (i&1)     // 当前层
#define v (!u)      // 上一层
    
    memset(dp,-0x3f,sizeof(dp)); // 初始化DP为负无穷
    dp[!(n&1)][w][0]=0; // 初始状态:在车站n,满载w件货物,距离0,价值0
    
    // 从后向前遍历车站(从n到2)
    for(int i=n;i>1;i--){
        // 情况1:空车到达车站i(从更远的车站返回)
        for(int k=0;k<i*2-2;k++)
            dp[u][1][k]=dp[v][1][k]; // 距离不够,无法从远处返回
        for(int k=i*2-2;k<=d;k++)
            dp[u][1][k]=max(dp[v][1][k],dp[v][w][k-i*2+2]+a[i]);
            // 要么保持原状,要么从满载状态行驶2*(i-1)距离后到达
        
        if(w==1)continue; // 如果容量为1,跳过下面的转移
        
        // 情况2:非空车到达车站i(继续收集货物)
        for(int j=2;j<=w;j++)
            for(int k=0;k<=d;k++)
                dp[u][j][k]=max(dp[v][j][k],dp[v][j-1][k]+a[i]);
                // 要么保持原状,要么多装一件当前车站的货物
    }
    
    // 在所有可能的状态中找最大值
    for(int j=1;j<=w;j++)
        for(int k=0;k<=d;k++)
            ans=max(ans,dp[0][j][k]);
    cout<<ans;
    return 0;
}

 

posted @ 2025-10-30 21:44  CRt0729  阅读(3)  评论(0)    收藏  举报