首页 > 其他分享 >P1070 [NOIP2009 普及组] 道路游戏

P1070 [NOIP2009 普及组] 道路游戏

时间:2024-12-14 20:21:19浏览次数:13  
标签:普及 le return int NOIP2009 对角线 1005 最优 P1070

Problem

Solve

此题是求最优解,考虑贪心时会发现这个不满足局部最优->整体最优,故考虑DP
通过输入格式能受到启发,时间可以作为维度之一,所以定义为:
\(f_{i,j}\)第i秒末,机器人在j号工厂能获得的最大金币
因为机器存在时间有上限,所以推的时候枚举本次机器人到底走了多少步,然后从走之前推过来(如图1)
动态转移方程为$$f_{i,j}=max(f_{i-k,j-k}+\sum_{l=0}^{k-1} a_{i-l,j-l}) (k\le p)$$
当然这个仅仅是大部分情况下的版本,有时会从n->1,这种情况将后半部分拆成两个部分即可(如图2)
解为\(max(f_{m,i})(i\le n)\),时间复杂度\(O(nmp)\)

优化

不难发现,我们都在寻找当前时刻近p秒内的最优解,可以使用单调队列
我们给每个对角线建立单调队列,这样就能直接找出最优的位置了,前半部分可以O(1)解决
对于后半部分,我们给每个对角线维护前缀和即可
对角线的编号建议为为i-j,这样可以一一对应,十分方便,具体参照代码,时间复杂度\(O(nm)\)

理论上不加优化的解法是TLE90,但是在洛谷神机+常数优化+O2的情况下能将理论\(10^9\)的计算量压在500ms内,所以代码给出的是理论90+前缀和维护后半部分的写法

Code

#include<bits/stdc++.h>
using namespace std;
int n,m,p,a[1005][1005],b[1005];
int f[1005][1005],s[2005][1005],maxn[1005];
int fg(int j,int k){
    if((j-k+1000*n)%n==0)return n;
    return (j-k+1000*n)%n;
}
int fs(int i,int j,int k){
    int ret=0;
    if(j-k<0){
        ret+=s[i-j+1000][i];
        ret+=s[i-j-n+1000][i-j]-s[i-j-n+1000][i-k];
    }else if(j==k){
        ret+=s[i-j+1000][i];
    }else ret=s[i-j+1000][i]-s[i-j+1000][i-k];
    ret-=b[fg(j,k)];
    return ret;
}
int main(){
    memset(f,-0x3f,sizeof(f));
    memset(maxn,-0x3f,sizeof(maxn));
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++)f[0][i]=0;
    maxn[0]=0;
    for(int i=2;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[j][i]);
        }
    }
    for(int j=1;j<=m;j++){
        scanf("%d",&a[j][1]);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            s[i-j+1000][i]=s[i-j+1000][i-1]+a[i][j];
        }
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            for(int k=1;k<=p;k++){
                if(i-k<0)break;
                f[i][j]=max(f[i][j],maxn[i-k]+fs(i,j,k));
            }
            maxn[i]=max(maxn[i],f[i][j]);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=max(ans,f[m][i]);
    }
    cout<<ans;
    return 0;
}

图一image
图二image

标签:普及,le,return,int,NOIP2009,对角线,1005,最优,P1070
From: https://www.cnblogs.com/yiweixxs/p/18607119

相关文章