题目大意:
都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:

为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)


解题思路:1)由题目可以知道,在某个时间点在某点接住馅饼,则前一个时间点必须在这个点的左边,右边或者就在这个点。
              2)根据题设,我们不妨设dp[i][j]为在第i秒在j处接住的馅饼。
                      则有:    dp[i][j]=Max{dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]}+a[i][j];


代码
 1#include <iostream>
 2#include <cstdio>
 3#include <cmath>
 4#include <algorithm>
 5#include <cstring>
 6
 7using namespace std;
 8
 9int a[100010][15];
10int dp[100010][15];
11int t,n,p,q,maxx;
12
13int main()
14{
15    while (~scanf("%d",&n))
16    {
17        if (n==0break;
18        t=-(1<<30);
19        memset(a,0,sizeof(a));
20        memset(dp,0,sizeof(dp));
21        for (int i=1; i<=n; i++)
22          {
23              cin >> p >> q;
24              a[q][p]++;
25              if (t<q) t=q;
26          }

27        dp[1][5]=a[1][5];
28        dp[1][6]=a[1][6];
29        dp[1][4]=a[1][4];
30        for (int i=1; i<=t-1; i++)
31        {
32             for (int j=0; j<=10; j++)
33             {
34                 if (dp[i+1][j+1]<a[i+1][j+1]+dp[i][j] && j<10)
35                    dp[i+1][j+1]=dp[i][j]+a[i+1][j+1];
36                 if (dp[i+1][j]<a[i+1][j]+dp[i][j])
37                    dp[i+1][j]=dp[i][j]+a[i+1][j];
38                 if (dp[i+1][j-1]<a[i+1][j-1]+dp[i][j] && j>0)
39                    dp[i+1][j-1]=dp[i][j]+a[i+1][j-1];
40             }

41        }

42        maxx=-(1<<30);
43        for (int i=1; i<=11; i++)
44           if (dp[t][i]>maxx) maxx=dp[t][i];
45        cout << maxx << endl;
46    }

47    return 0;
48}

49