P1070 [NOIP2009 普及组] 道路游戏

dfs-> dp[i]=max(dp[i],dp[i-k]+∑-cost[ last ])

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------debug\n");
using namespace std;

int n,m,p,dp[1005],a[1005][1005],cost[1005];

int main()
{
    ios::sync_with_stdio(false);
    memset(dp,-0x3f3f3f3f,sizeof(dp));
    
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++) 
    {
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    }
    for(int i=1;i<=n;i++) cin>>cost[i];
    
    dp[0]=0;//side val
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int sum=0;
            for(int k=1;k<=i&&k<=p;k++)
            {
                int last;
                if(j-k<=0) last=n+(j-k)%n;
                else last=j-k;
                
                sum+=a[last][1+i-k];
                dp[i]=max(dp[i],dp[i-k]-cost[last]+sum);
            }
        }
    }
    cout<<dp[m];
    return 0;
}





















/*
#include <iostream>
#include <cstring>
using namespace std;
int a[1005][1005],cost[1005];
int dp[1005]; 
int main()
{
    int n,m,p;
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
    for(int i=1;i<=n;i++) cin>>cost[i];
    
    memset(dp,~0x7f,sizeof(dp));  
    //注意初始化,一定要附一个极小的值,因为计算过程中可能会出现负数!
    
    for(int i=1;i<=m;i++) //枚举时间,前i分钟 
    {
        for(int j=1;j<=n;j++) //枚举结束位置,以j号工厂结束 
        {
            int sum=0;  
            for(int k=1;k<=p && k<=i;k++)
            {
                int last;  //last表示走k步前,工厂是多少号
                if(j-k<=0) last=n+(j-k)%n;
                else last=j-k;   //环形道路 
                sum+=a[last][i-k+1];  //求和 
                dp[i]=max(dp[i],dp[i-k]+sum-cost[last]);  
                //状态转移方程,第i分钟的最大值=max(前i-k分钟最大值+走过来得到金币数) 
            }
        }
    }
    cout<<dp[m]; //第m分钟的最大值,及答案 
    return 0;
}
*/
View Code

 


 

 

 
posted @ 2023-07-11 08:46  JMXZ  阅读(7)  评论(0)    收藏  举报