HDU 1176 免费馅饼:dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1176
题意:
横坐标范围为[0,10],你在第0秒站在坐标为5的地方。
在接下来的一段时间内,会有n个馅饼落下来,每一个馅饼有一个位置x和时刻t。
每一秒你最多可以移动1格。并且在某一个时刻,你只能接到你当前位置的馅饼。
问你最多能接到多少馅饼。
题解:
表示状态:
dp[i][j] = max num of pancakes
(1)第i秒
(2)站在j的位置
如何转移:
当前dp[i][j]取决于i-1秒时j-1,j,j+1三个位置接馅饼的情况。
但是,更新dp[i][j]的前提是上一个状态是可以达到的。比如说你第0秒在位置5,那么你不可能在第1秒到达位置10。
所以一开始要将所有dp设为-1,表示不可到达。
So...
if(dp[i-1][j-1]!=-1) dp[i][j] = max(dp[i][j], dp[i-1][j-1]);
if(dp[i-1][j]!=-1) dp[i][j] = max(dp[i][j], dp[i-1][j]);
if(dp[i-1][j+1]!=-1) dp[i][j] = max(dp[i][j], dp[i-1][j+1]);
另外还要加上现在第i秒接到的馅饼数:
if(dp[i][j]!=-1) dp[i][j] += w[i][j];
边界条件:
你在第0秒时,站在位置5,接到了0个馅饼。
(为了防止数组越界,给所有坐标+1)
所以dp[0][6] = 0;
AC Code:
1 // dp[i][j] = max num of pancakes 2 // dp[i][j] = max(dp[i-1][j-1], dp[i-1][j], dp[i-1][j+1]) + w[i][j] 3 // edge: dp[5][0] 4 // enumerate: 5 // i: 1 to maxt 6 // j: 1 to 11 7 8 #include <iostream> 9 #include <stdio.h> 10 #include <string.h> 11 #define MAX_X 15 12 #define MAX_T 100005 13 14 using namespace std; 15 16 int n; 17 int x,t; 18 int ans; 19 int maxt; 20 int w[MAX_T][MAX_X]; 21 int dp[MAX_T][MAX_X]; 22 23 int main() 24 { 25 while(scanf("%d",&n)!=EOF) 26 { 27 if(n==0) break; 28 memset(w,0,sizeof(w)); 29 memset(dp,-1,sizeof(dp)); 30 ans=0; 31 maxt=0; 32 dp[0][6]=0; 33 for(int i=0;i<n;i++) 34 { 35 scanf("%d%d",&x,&t); 36 w[t][x+1]++; 37 maxt=max(maxt,t); 38 } 39 for(int i=1;i<=maxt;i++) 40 { 41 for(int j=1;j<=11;j++) 42 { 43 if(dp[i-1][j-1]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-1]); 44 if(dp[i-1][j]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j]); 45 if(dp[i-1][j+1]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j+1]); 46 if(dp[i][j]!=-1) dp[i][j]+=w[i][j]; 47 ans=max(ans,dp[i][j]); 48 } 49 } 50 printf("%d\n",ans); 51 } 52 }