动态规划数塔类型题目总结Word格式.docx
《动态规划数塔类型题目总结Word格式.docx》由会员分享,可在线阅读,更多相关《动态规划数塔类型题目总结Word格式.docx(6页珍藏版)》请在冰豆网上搜索。
intmain(void)
{
intn,m,i,k,j;
scanf("
%d"
&
m);
while(m-->
0)
{
n);
k=(1+n)*n/2;
for(i=1;
i<
=k;
i++)
a+i);
}
k=k-n;
for(i=k,j=0;
i>
=1;
i--)
a[i]=a[i]+Max(a[i+n],a[i+n-1]);
if(++j==n-1)
n--;
j=0;
printf("
%d\n"
a[1]);
return0;
}
首先什么是“数塔类型”?
从某一点转向另一点或者说是从某一状态转向另一状态,有多种选择方式(比如这里的9->
12,9->
15),从中选取一条能产生最优值的路径。
这类问题的思考方法:
假设后续步骤的结果已知,比如这里假设已经知道沿12方向的最大值x和沿15方向的最大值y。
接下来看几个题,加深印象吧
1.免费馅饼问题
5(起始位置)
4
|
5
6
3
|
6
|
5
7
..................
和“数塔”一样,它也是从某一点出发,有多个选择的问题(往前走一步,呆在原地,往后走一步)从中选择一条最优值路径(获得馅饼最多)。
还是按照“数塔”的思考方式,我们可以假设“已经求得”下一个站在位置4获得的最大值x和呆在原地获得的最大值y以及站在位置6获得的最大值z,那么对于起始位置5获得最大值就是Max(x,y,z),因此可以得到状态转移方程为:
m[t][x]=Max(m[t+1][x-1],m[t+1][x],m[t+1][x+1])
并且我们可以通过“列表格”的方式,自底向上求解:
string.h>
#defineN100000
inta[N][11];
intMax(inta,intb,intc)
intn;
n=a>
b?
a:
b;
returnn>
c?
n:
c;
intn,x,t,max,i;
while(scanf("
n))
if(!
n)break;
max=0;
memset(a,0,sizeof(a));
for(i=0;
n;
%d%d"
x,&
t);
a[t][x]+=1;
if(t>
max)max=t;
//DP
for(t=max-1;
t>
=0;
t--)
a[t][0]+=Max(0,a[t+1][0],a[t+1][1]);
for(x=1;
x<
10;
x++)
a[t][x]+=Max(a[t+1][x-1],a[t+1][x],a[t+1][x+1]);
a[t][10]+=Max(a[t+1][9],a[t+1][10],0);
a[0][5]);
2.滑雪问题
上
左
A
右
下
依然和“数塔”一样,从某一点出发,面临多个选择(往上,往左,往下,往右)从中选择一条最优值路径(滑雪距离最长)
若对A点求,很显然它的最大值就为:
Max(上,右,下,左)+1
因此对于任意位置[i,j],其状态转移方程为:
m[i][j]=Max(m[i-1][j],m[i][j+1],m[i+1][j],m[i][j-1])+1
由于这道题很难画出它的路径图(起点和终点都不知道)因此很难用“列表格”的方式自底向上求解,因此我们采用备忘录法:
#defineN101
inta[N][N],m[N][N],r,c;
intOK(inti,intj)
return(i>
=1&
&
=r&
j>
j<
=c);
intsearch(inti,intj)
intk;
if(m[i][j]>
0)returnm[i][j];
if(OK(i-1,j)&
a[i][j]>
a[i-1][j])
k=search(i-1,j)+1;
m[i][j]=m[i][j]<
k?
k:
m[i][j];
if(OK(i,j+1)&
a[i][j+1])
k=search(i,j+1)+1;
if(OK(i+1,j)&
a[i+1][j])
k=search(i+1,j)+1;
if(OK(i,j-1)&
a[i][j-1])
k=search(i,j-1)+1;
returnm[i][j];
inti,j,k,t;
&
r,&
c)!
=EOF)
=r;
i++)
for(j=1;
=c;
j++)
a[i][j]);
memset(m,0,sizeof(m));
k=0;
t=search(i,j);
k=k<
t?
t:
k;
k+1);
3.Worm问题,这题和免费馅饼几乎是一样的,我们同样可以使用“列表格”的方式自底向上求解:
#defineN100
inta[N][N];
intt,x,n,p,m,T;
%d%d%d%d"
n,&
p,&
m,&
T)!
=EOF)//苹果树n,毛毛虫其实位置p,m分钟,终点位置T
{
memset(a,0,sizeof(a));
a[m][T]=1;
for(t=m-1;
a[t][1]+=a[t+1][2];
for(x=2;
a[t][x]+=a[t+1][x-1]+a[t+1][x+1];
a[t][n]+=a[t+1][n-1];
a[0][p]);