http://acm.hdu.edu.cn/showproblem.php?pid=1176
开始对dp有感觉了,就是能够覆盖所有的状态,而且要有状态转移方程,即递推关系。
那么这题就是,利用dp【i】【j】表示在第i秒在位置j可以获得的最大面包数,那么他可能从前一秒的左边,或者右边,或者原地不动来,那么着就是状态了。
对于0和10这两个点要特殊处理。
因为第一秒在位置5,所以初始化的时候要把第一秒的初始化了。
初始化:
dp[1][4]=map[1][4];
dp[1][5]=map[1][5];
dp[1][6]=map[1][6];
状态转移:
dp[i][j]=max(max(dp[i-1][j-1],dp[i-1][j+1]),dp[i-1][j])+map[i][j];
View Code
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #define maxn 150000 using namespace std; int map[maxn][20]; int dp[maxn][20]; int n; int main() { while(scanf("%d",&n)) { if(!n)break; memset(dp,0,sizeof(dp)); memset(map,0,sizeof(map)); int big=0; for(int i=0;i<n;i++) { int a,t; scanf("%d%d",&a,&t); map[t][a]++; big=max(big,t); } dp[1][4]=map[1][4]; dp[1][5]=map[1][5]; dp[1][6]=map[1][6];//初始化第一秒的有三个位置 for(int i=2;i<=big;i++)//从第2秒到最大时间dp { for(int j=0;j<=10;j++) { if(j==0) dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+map[i][j];//对于0点特殊 else if(j==10) dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+map[i][j];//对于10点特殊 else dp[i][j]=max(max(dp[i-1][j-1],dp[i-1][j+1]),dp[i-1][j])+map[i][j];//状态转移 } } int ans=0; for(int i=0;i<=10;i++)//遍历找出最大值 ans=max(ans,dp[big][i]); printf("%d\n",ans); } return 0; }