传送门:点击打开链接

解题思路:动态规划基础题,在第0秒时(也就是起点)在5这个位置,然后本位置,左右位置选择一个往下走,于是得到的子问题就是:下一次要到本位置,左位置,右位置其中一个,特别的在边界位置特殊处理。以下有定义状态和转移方程。请注意,如果用数组递推完成动态规划过程要从最后一秒往前规划,你可以这样想,从11个位置任选一个进行上述规划,终点是5这个位置。因为你想,原题意让你从5这个位置出发,最终是不是可能到达11个位置的任意一个位置,(Ps:如果到达不了,最大时间必定小于5,但结果无影响),逆过来,从终点出发也可以。其实本题类似于数塔。可以用数塔思路解本题,边界问题和转移方程处理一下就OK。

AC代码如下:

/*

状态:dp[i][j]:在第i秒第j个位置所得到的最多个饼
转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j+1],dp[i-1][j-1])+book[i][j];

*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int book[100002][12],dp[100002][12];

int max(int a,int b)
{
	return a>b?a:b;
}

int main()
{
	int i,j,n,time,point,Tmax;
	while(~scanf("%d",&n) && n)
	{
		memset(book,0,sizeof(book));
		memset(dp,0,sizeof(dp));
		for(i=Tmax=0;i<n;i++)
		{
			cin>>point>>time;
			book[time][point]++;
			if(time>Tmax)
				Tmax=time;
		}
		for(i=Tmax;i>=0;i--)
		{
			dp[i][0]=max(dp[i+1][0],dp[i+1][1])+book[i][0];
			for(j=1;j<=10;j++)
				dp[i][j]=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))+book[i][j];
		}
		cout<<dp[0][5]<<endl;
	}
	return 0;
}