HDU 1176 免費餡餅 (DP+數塔問題)
阿新 • • 發佈:2018-11-11
題目連結: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,真是深刻的教訓,不是什麼時候都是領接表好的,這種資料不大的情況,建一個領接矩陣搜尋起來是真的是又快又準