题目链接: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,真是深刻的教训,不是什么时候都是领接表好的,这种数据不大的情况,建一个领接矩阵搜索起来是真的是又快又准