题目大意:
都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:
为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼)Input
输入数据有多组。每组数据的第一行为以正整数n(0<n<100000),表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T(0<T<100000),表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。
Output
每一组输入数据对应一行输出。输出一个整数m,表示gameboy最多可能接到m个馅饼。
提示:本题的输入数据量比较大,建议用scanf读入,用cin可能会超时。
Sample Input
6 5 1 4 1 6 1 7 2 7 2 8 3 0Sample Output
4题解:
状态:
dp[i][j]表示第i时刻在j位置接到的最多馅饼。
状态转移方程:
dp[i][j]=max(dp[i+1][j],dp[i+1][j-1],dp[i+1][j+1])+num[j][i]
从第i+1时刻后在j位置,j-1位置和j+1位置能够得到最多馅饼中取最大值
然后再加上第i时刻在j位置能够接到的馅饼。
最后我们考虑逆着枚举时间,类似于数塔的思想。
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<cstdlib> #include<vector> #include<map> #include<set> #include<stack> #include<queue> #define PI atan(1.0)*4 #define E 2.718281828 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a=0,b=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') b=-1; c=getchar(); } while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+c-'0'; c=getchar(); } return a*b; } const int INF = 0x3f3f3f3f; const int N = 1e5+7; int dp[N][15]; int num[15][N]; //dp[i][j]表示第i时刻之后在j位置接到的最多馅饼 //num[i][j]表示在第j时刻在i位置能够接到的馅饼 /* 状态转移方程: dp[i][j]=max(dp[i+1][j],dp[i+1][j-1],dp[i+1][j+1])+num[j][i] 从第i+1时刻后在j位置,j-1位置和j+1位置能够得到最多馅饼中取最大值 然后再加上第i时刻在j位置能够接到的馅饼 */ inline int max(int a,int b,int c){ int Max=a>b?a:b; return Max>c?Max:c; } inline void init(){ mst(num,0); mst(dp,0); } int main(){ int n; while(~scanf("%d",&n)&&n){ init(); int MAX=0;//记录最大时刻 rp(i,1,n){ int x=read(),T=read(); x++; num[x][T]++; MAX=max(T,MAX); } RP(i,MAX,0) rp(j,1,11) dp[i][j]=max(dp[i+1][j],dp[i+1][j+1],dp[i+1][j-1])+num[j][i]; printf("%d\n",dp[0][6]); } return 0; }
dp训练计划——hdu1176逆序dp
最新推荐文章于 2022-06-27 00:40:14 发布