[dp专题]G免费馅饼
免费馅饼
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 29065 Accepted Submission(s): 9921
Problem Description
都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标:
为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问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可能会超时。
提示:本题的输入数据量比较大,建议用scanf读入,用cin可能会超时。
Sample Input
6
5 1
4 1
6 1
7 2
7 2
8 3
0
Sample Output
4
Author
lwg
二维dp
状态转移方程也很容易想到
dp[i][j]表示在时间i,位置J的时候能得到的馅饼的个数。
dp[i][j]是由dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]得到。
注意边界和初始化。
因为一开始是在位置5
所以 dp[1][4]=a[1][4];
dp[1][5]=a[1][5];
dp[1][6]=a[1][6];
但是取出最大的dp[i][j]的时候出了问题导致我一直WA,而且还没有想的很明白。。
AC代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 7 using namespace std; 8 9 int n,t,x,maxtime; 10 long long ans; 11 const int N=1E5+7; 12 int a[N][15],dp[N][15]; 13 14 int MAX(int a,int b,int c) 15 { 16 int res = -1; 17 if ( a>res ) 18 res = a; 19 if ( b>res ) 20 res = b; 21 if ( c>res ) 22 res = c; 23 return res; 24 } 25 26 int main() 27 { 28 while ( scanf("%d",&n)!=EOF&&n ) 29 { 30 ans = -1 ; 31 maxtime = -1; 32 memset(a,0,sizeof(a)); 33 memset(dp,0,sizeof(dp)); 34 for ( int i = 1 ; i <= n ; i++ ) 35 { 36 scanf("%d %d",&x,&t); 37 a[t][x]++; 38 if ( t>maxtime ) 39 maxtime = t; 40 } 41 dp[1][4] = a[1][4]; 42 dp[1][5] = a[1][5]; 43 dp[1][6] = a[1][6]; 44 for ( int i = 2 ; i <= maxtime ; i++ ) 45 for ( int j = 0 ; j <= 10 ; j++ ) 46 { 47 if ( j==0 ) 48 dp[i][j] = max(dp[i-1][j],dp[i-1][j+1]) + a[i][j]; 49 else if ( j==10 ) 50 dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + a[i][j]; 51 else dp[i][j] = MAX(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+a[i][j]; 52 // if ( dp[i][j]>ans ) 53 // ans = dp[i][j]; 54 55 } 56 for ( int i = 0 ; i <= 10 ; i++) 57 if ( dp[maxtime][i]>ans ) 58 ans = dp[maxtime][i]; 59 printf("%I64d\n",ans); 60 61 } 62 return 0; 63 }
WA代码:
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int n,t,x,maxtime; long long ans; const int N=1E5+7; int a[N][15],dp[N][15]; int MAX(int a,int b,int c) { int res = -1; if ( a>res ) res = a; if ( b>res ) res = b; if ( c>res ) res = c; return res; } int main() { while ( scanf("%d",&n)!=EOF&&n ) { ans = -1 ; maxtime = -1; memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); for ( int i = 1 ; i <= n ; i++ ) { scanf("%d %d",&x,&t); a[t][x]++; if ( t>maxtime ) maxtime = t; } dp[1][4] = a[1][4]; dp[1][5] = a[1][5]; dp[1][6] = a[1][6]; for ( int i = 2 ; i <= maxtime ; i++ ) for ( int j = 0 ; j <= 10 ; j++ ) { if ( j==0 ) dp[i][j] = max(dp[i-1][j],dp[i-1][j+1]) + a[i][j]; else if ( j==10 ) dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) + a[i][j]; else dp[i][j] = MAX(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+a[i][j]; if ( dp[i][j]>ans ) ans = dp[i][j]; } // for ( int i = 0 ; i <= 10 ; i++) // if ( dp[maxtime][i]>ans ) // ans = dp[maxtime][i]; printf("%I64d\n",ans); } return 0; }