1. 程式人生 > >kuangbin專題十二 HDU1176 免費餡餅

kuangbin專題十二 HDU1176 免費餡餅

之前的dp專題有這道題,當時沒有寫出來,剛才第一次寫了正推的程式碼。沒有考慮到只能從5開始,WA。後來改了倒推。改了中間的小bug,過了。

思路:在一個點,可以接到 左中右 三個位置的餡餅,為了避免邊界處理,把可能下落的點0~10變為  1~11。 這樣1的 左中右 就是 0 1 2了。比較方便一點。

由於是倒推,所以初始化  dp[maxt][j] = f[maxt][j], maxt 為 最晚的時間。

狀態轉移方程:dp[i][j] = f[i][j] + max(dp[i+1][j-1], max(dp[i+1][j], dp[i+1][j+1]))

畫個樣例體會一下。倒數第二行開始,該點最大值 = 該點原值 + 下一時刻的三個位置的最大值,由於我的pos右移了一位,所以最後答案為 dp[0][6]

AC程式碼:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF =0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-5;
const ll mod = 1e9+7;
//head
int dp[100000 + 10][11 + 4];//dp[t][pos] 用時間倒推,dp[0][6]就是答案 
int f[100000 + 10][11 + 4];
int main() {
	int n, pos, t, maxt;
	while(~scanf("%d", &n)) {
		if(n == 0)
			break;
		mem(dp, 0);
		mem(f, 0);
		maxt = -1;
		while(n--) {
			scanf("%d%d", &pos, &t);//這裡讀取反了。。WA了 
			f[t][pos+1]++;
			maxt = max(maxt, t);
		}
		for(int i = 1; i <= 11; i++)
			dp[maxt][i] = f[maxt][i];//為了倒推,所以最後一行的f[i][j] 即為 dp[i][j] 
		for(int i = maxt-1; i >= 0; i--) {//核心程式碼 
			for(int j = 1; j <= 11; j++) {
				dp[i][j] = f[i][j] + max(dp[i+1][j-1], max(dp[i+1][j], dp[i+1][j+1]));
			}
		}
		printf("%d\n", dp[0][6]);
	}
}