POJ 3661:Running 区间DP

Running

题目链接:

http://poj.org/problem?id=3661

题意:

有一只牛在跑步,在第 i 分钟它可以跑Ni米,疲惫值加1(疲惫值初始为0),或者休息一分钟,疲惫值减1(只有疲惫值到了0才能重新开始跑步),当匹配值达到M时它必须休息,且第N分钟结束时牛的疲惫值必须为0,求这只牛最远可以跑几米。

题解:

设dp[i][j]在 i 分钟里疲惫值限制为j的情况下牛可以跑的最远距离。一般情况下这样设就行了,但是因为题目限制只要开始休息就必须休息到疲惫值为0,所以这里将dp再加一重变成dp[i][j][0]和dp[i][j][1],分别代表在第 i 分钟能量为 j 时是休息还是继续跑步

很明显dp[i][j][0]是dp[i-1][j+1][0]和dp[i-1][j+1][1]间的较大值,注意当j==0的时候dp[i][j][0]还可以由dp[i-1][j][0]得到(即上一分钟能量已经为0,但是这一分钟还是休息)

而dp[i][j][1]=dp[i-1][j-1][1]+a[i](上一分钟跑步,这一分钟还在跑步),同样,这里也要注意一点,当j==1时dp[i][j][1]还可以由dp[i-1][j+1][1]+a[i]得到(上一分钟休息且疲惫值归0了)

              

代码

#include<stdio.h>
#include<string.h>
const int N=10001;
const int M=501;
int dp[N][M][2];
int mmax(int x,int y)
{
	return x>y?x:y;
}
void solve()
{
	int n,m,x;
	memset(dp,0,sizeof(dp));
	while(~scanf("%d%d",&n,&m))
	{ 
		for(int i=1;i<=n;++i)
		{
			scanf("%d",&x);
			for(int j=0;j<=m;++j)
			{
				if(j!=0)
				{
					dp[i][j][1]=dp[i-1][j-1][1]+x;
					if(j==1)dp[i][j][1]=mmax(dp[i][j][1],dp[i-1][j-1][0]+x);
				}
				if(j!=m)
				{
					dp[i][j][0]=mmax(dp[i-1][j+1][0],dp[i-1][j+1][1]);
					if(j==0)dp[i][j][0]=mmax(dp[i][j][0],dp[i-1][j][0]);
				}
			}
		}
		printf("%d
",dp[n][0][0]);
	}
}
int main()
{
	solve();
	return 0;
}
 
原文地址:https://www.cnblogs.com/kiuhghcsc/p/5750084.html