6 5 1 4 1 6 1 7 2 7 2 8 3 0
4
我们定义数组dp【i】【j】表示第i秒在位子j处获得的最大馅饼数,因为起点是确定的,我们可以把问题逆向思考这样来看:起点无所谓,但是终点一定要到达位子5处,求最大接馅饼数,也就是说,我们把时间也逆着来看。
那么不难写出状态转移方程:
DP【i】【j】=max(dp【i+1】【j】,dp【i+1】【j-1】,dp【i+1】【j+1】)+a【i】【j】;
翻译上述状态转移方程:假设人物在第i秒的时候处于j位子,(因为我们逆序考虑问题了),那么人物在第i+1秒的时候处在j,j-1,j+1的位子都可以在第i秒的时候到达位子j。
注意处理j==0和j==10的时候的特殊情况。
AC代码:
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int a[140000][15]; int dp[140000][15]; int main() { int n; while(~scanf("%d",&n)) { if(n==0)break; memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); int maxntime=0; for(int i=0;i<n;i++) { int p,t; scanf("%d%d",&p,&t); a[t][p]++; maxntime=max(maxntime,t); } for(int i=maxntime;i>=0;i--) { for(int j=0;j<11;j++) { if(i==maxntime)dp[i][j]=a[i][j]; if(j==0) { dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j]; continue; } if(j==11) { dp[i][j]=max(dp[i+1][j],dp[i+1][j-1])+a[i][j]; continue; } dp[i][j]=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))+a[i][j]; } } //printf("%d\n",max(dp[1][5],max(dp[1][4],dp[1][6]))); printf("%d\n",dp[0][5]); } }