【题解】洛谷P1070 道路游戏(n^3)

原题数据范围比较诡异,最后一个点明明n^2才能过,结果n^3也过了,所以写一下这个做法吧。

设一个数组dp表示一定时间内能获得收益的最大值,to[i][j]表示从第i时刻到第j时刻所获收益的最大值,可以得到状态转移方程dp[i]=max(dp[i],dp[j]+to[j][i])。

对于数组to[i][j],为了求它的最优情况,我们可以通过循环来解决,由于读入时对于在m时刻获得的金币我们用一个图来存了下来,而沿对角线可以得到to数组的答案,枚举第i个机器人,枚举j当前时刻,再枚举行走的步数k,k<=p并且k+j<=m,设sum为-cost[i]因为机器人要花钱,设定t代表其对角线的横坐标(这里t=i+k-1,但我也不知道为啥。。。),如果t比n大,因为是环形的道路,所以需要从开头的1号工厂出发所以t-=n,那么求得其对角线和为sum+=a[t][j+k]。得到最优情况to[j][j+k]=max(to[j][j+k],sum)

这个做法n^3,对于普及组的难度应该够了吧。。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,p;
int dp[1010];
int a[1010][1010];
int cost[1010];
int to[1010][1010];
int main()
{
	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];
	for(int i=0;i<=m;i++)
		for(int j=i+1;j<=m;j++)
			to[i][j]=-1e9;
			
	for(int i=1;i<=n;i++)
		for(int j=0;j<=m;j++)
		{
			int sum=-cost[i];
			for(int k=1;k<=p&&k+j<=m;k++)
			{
				int t=i+k-1;
				if(t>n) t-=n;
				sum+=a[t][j+k];
				to[j][j+k]=max(to[j][j+k],sum);	
			} 
		}
			
	for(int i=1;i<=m;i++)
	{
		dp[i]=-1e9;
	}	
	dp[0]=0;
	for(int i=1;i<=m;i++)
		for(int j=0;j<i;j++)
			dp[i]=max(dp[i],dp[j]+to[j][i]);
			
	cout<<dp[m]<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81087626