kuangbin專題十二 HDU1176 免費餡餅
阿新 • • 發佈:2019-01-22
之前的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]); } }