hdu 1176 免费馅饼 (dp)

题目链接

中文题,题目描述不再多说,直接说思路。

首先是状态转移,用dp[ i ][ j ]表示第 i 时刻在第 j 位置能接到的最大馅饼数目,状态来源有三

  1. 上一时刻左边位置转移过来
  2. 上一时刻右边位置转移过来
  3. 上一时刻当前位置转移过来

 因此我们得出了状态的转移过程,有一个问题在于,如何存放输入的数据能方便我们计算呢

如果我们用一个二维数组a[ i ][ j ]表示在 i 时刻有 j 个馅饼掉落,将数组初始化为0,对于输入每一个时刻每一个位置,每次执行自增操作即可,这样在写状态转移方程的时候就会方便很多(方法是借鉴大佬的,orzorz)

还有一个小细节,就是我们并不知道我们的终点实在哪个时刻哪个位置,如果正向进行的话我们需要规定一个时刻,去便利最终时刻的所有位置求最大值,但是如果我们逆向进行循环就不用那么多顾虑,因为我们的起点是已知的,最后直接输出 0 时刻起点的值即可

由此可以得到状态转移方程

dp[i][j] = dp[i + 1][j] + a[i + 1][j];
if(j >= 1) dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + a[i + 1][j - 1]);
if(j <= 9) dp[i][j] = max(dp[i][j], dp[i + 1][j + 1] + a[i + 1][j + 1]);

完整代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int maxn = 1e5 + 10;
int n, x, t;
int dp[maxn][11], a[maxn][11];
int main()
{
	while (~scanf("%d", &n) && n){
		memset(dp, 0, sizeof dp);
		memset(a, 0, sizeof a);
		for (int i = 1; i <= n; i++){
			scanf("%d %d", &x, &t);
			a[t][x]++;
		}
		for (int i = maxn - 10; i >= 0; i--){
			for (int j = 0; j <= 10; j++){
				dp[i][j] = dp[i + 1][j] + a[i + 1][j];
				if(j >= 1) dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + a[i + 1][j - 1]);
				if(j <= 9) dp[i][j] = max(dp[i][j], dp[i + 1][j + 1] + a[i + 1][j + 1]);
			}
		}
		printf("%d\n", dp[0][5]);
	}
	return 0;
}

 

posted @ 2019-08-01 16:02  correct  阅读(56)  评论(0)    收藏  举报