1. 程式人生 > >HDU 1176 免費餡餅 (DP+數塔問題)

HDU 1176 免費餡餅 (DP+數塔問題)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1176
題目大意:在一個0到10的閉區間中,會不定期有餡餅掉落,主角一開始在5號位置,他每秒只能移動一個位置,比如第一秒主角在5號位置,第二秒主角只能在4,5,6號位置。輸入N組資料,問主角最大能接多少餅。
雖然一眼就看出來是用DP了,但一開始選擇了記憶化搜尋(因為最近都在用這個方法),然後華麗麗的T了,於是只能選擇遞推法,把整個圖畫出來,發現這道題本質和數字金字塔很像(不知道這個東西的同學可以百度一下),於是照著數字金字塔寫了一個狀態方程
dp[i][j]=max(max(dp[i-1][j+1],dp[i][j+1]),dp[i+1][j+1])
然後程式碼就出來了,WA了一次,原因是我沒有初始化……(低階錯誤)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=100005;
int n;
int dp[15][maxn];
int arr[15][maxn];
int tmax;
int main()
{
	while(cin>>n)
	{
		if(n==0)break;
		tmax=0;
		memset(arr,0,sizeof arr);
		memset(dp,0,sizeof dp)
; for(int i=0;i<n;i++) { int a,b; scanf("%d%d",&a,&b); if(b>tmax)tmax=b; arr[a][b]++; } for(int i=tmax-1;i>=0;i--) { for(int j=0;j<=10;j++) { int aa,bb,cc; aa=0; bb=0; cc=0; if(j-1>=0)aa=dp[j-1][i+1]+arr[j-1][i+1]; if(j>=0)bb=dp[j]
[i+1]+arr[j][i+1]; if(j+1<=10)cc=dp[j+1][i+1]+arr[j+1][i+1]; dp[j][i]=max(max(aa,bb),cc); } } printf("%d\n",dp[5][0]+arr[5][0]); } }

後記:在寫完這篇部落格後我越想越不對,遞推DP程式跑的很快,也就幾十毫秒,憑什麼記憶化搜尋就會超時,於是我懷疑是領接表的鍋(因為我第一遍用的是領接表,第二遍用的是領接矩陣)於是我重新寫了一遍記憶化搜尋,果然也過了,也就比遞推DP慢了20ms,真是深刻的教訓,不是什麼時候都是領接表好的,這種資料不大的情況,建一個領接矩陣搜尋起來是真的是又快又準