道路游戏 动态规划

【问题描述】

小新正在玩一个电脑游戏

有一条环形路,路上有n个机器人工厂,顺时针方向编号1~n,相邻工厂之间的n段路编号1~n,规定i连接ii+1工厂,n连接n1工厂。

游戏,每分钟每段路上都会出现一些金币,不同时间同一路段出现的金币数可能不同。小新需要操控机器人收集金币。机器人必须在工厂购买,购买后机器人顺路行走,每分钟走一段路收集路上的所有金币i号厂买机器人,i号厂开始,1分钟经过i号路,到i+1号厂,并收集i号路的所有金币。

环形路上同时只能有1机器人,每个机器人最多连续p分钟,中断行走或走完p分钟它会自动消失

以下是补充说明:

1、游戏从小新第一次购买机器人开始计时。

2、购买机器人瞬间完成。

3、购买机器人的费用在同一工厂相同,但在不同工厂不一定相同。

4、购买机器人的金币,游戏结束时从收集的金币中扣除因此,最终的金币数可为负。

现在已知分钟每段路出现的金币数,以及在每个厂购买机器人用。

请你计算:经过m分钟后,扣除购买机器人的花费,小新最多能到多少金币。

【输入】第一行nmp

下接n行,每行m个整数,一个空格相隔

i行第j个数:表示第j分钟i号路的金币数(1≤金币数≤100)。

最后一行n个整数,一个空格相隔

i个数表示在i号厂买机器人金币数(1≤金币数≤100)。

【输出】1个整数,表示最多能得金币

【样例】

game.in

game.out

2 3 2

1 2 3

2 3 4

1 2

5

【数据范围】

对于40%的数据,2≤n≤401≤m≤40

对于90%的数据,2≤n≤2001≤m≤200

对于100%的数据,2≤n≤10001≤m≤10001≤p≤m


附AC码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int f[1010][1010];
int t[1010][1010];
int b[1010][1010];
int cost[1010];
int q[1010]={0};
int main(){
	//freopen("game.in","r",stdin);
	//freopen("game.out","w",stdout);
    int i,j,k,m,n,p,qmax=0,nmax=0;
	scanf("%d%d%d",&n,&m,&p);
	for(i=1;i<=n;i++)
	    for(j=1;j<=m;j++)
	        scanf("%d",&b[j][i]);
	for(i=1;i<=n;i++)
	    scanf("%d",&cost[i]);
    for(i=1;i<=n;i++)
        q[i]=(i+n-2)%n+1;
    for(i=1;i<=n;i++)
        t[0][i]=p;
	for(i=1;i<=m;i++){
	    nmax=-214748368;
	    for(j=1;j<=n;j++){
		    if(t[i-1][q[j]]<p && f[i-1][q[j]]>qmax-cost[q[j]]){
				t[i][j]=t[i-1][j]+1;
			    f[i][j]=f[i-1][q[j]]+b[i][q[j]];
			}else{
			    t[i][j]=1;
			    f[i][j]=qmax-cost[q[j]]+b[i][q[j]];
			}
		    if(f[i][j]>nmax)nmax=f[i][j];
		}
		qmax=nmax;
	}
	printf("%d\n",nmax);
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值