传送门:点击打开链接
解题思路:动态规划基础题,在第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;
}