版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/83019789
题目
每次往上跳或往下掉或持平……(具体看题目吧),使路径上的权值和最大。
题解
记忆化搜索
设f[i][j][t]表示从出发点到(x,y)这个位置(不含这个位置,即减掉ma[x][y])还可以跳t次的最大权值和。
转移方程
,其中w表示这一路上的点权和。
下面说说前辈绕的弯路,
注意一下输入,第一行是底~
再注意一点,回到底后可以重置可跳次数~
考虑细致一点,这题还是不难的~
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=(1<<30)-1;
const int maxn=100010,maxm=25;
int n,m,cost1,cost2;
int ma[maxn][maxm];
int h,c;
int f[maxn][maxm][6];
int dfs(int x,int y,int t)//在(x,y)还能跳t次
{
if(y<1||y>m || t<0) return -inf;
if(~f[x][y][t]) return f[x][y][t];
if(ma[x][y]==-1) return f[x][y][t]=-inf;
if(x>=n) return f[x][y][t]=0;
int re;
/*if(y>1) re=dfs(x+1,y-1,t)+ma[x+1][y-1];//debug*/
if(y>2) re=dfs(x+1,y-1,t)+ma[x+1][y-1];//debug
else if(y==2) re=dfs(x+1,y-1,c)+ma[x+1][y-1];
else re=dfs(x+1,y,c)+ma[x+1][y];//re=max(re, dfs(x+1,y,t) );
int sum=0;
for(int i=1;i<=h;i++) sum+=ma[x+i][y+i];
re=max(re, dfs(x+h,y+h,t-1)+sum);
f[x][y][t]=re;
// printf("(%d %d %d %d)\n",x,y,t,f[x][y][t]);
return re;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&cost1,&cost2);
for(int i=1;i<=m;i++)//debug输入不要倒序 //i要倒序输入
for(int j=1;j<=n;j++) scanf("%d",&ma[j][i]);//debug ma[j][i]
int ans=-1,ansc,ansh;
for(c=1;c<=5;c++)//最大连跳c次
{
for(h=1;h*c<m;h++)//跳跃高度为h
{
memset(f,-1,sizeof(f));
// puts("--------------------------------------------");
int tmp=dfs(0,1,c)-cost1*(h-1)-cost2*(c-1);
if(tmp>ans)
{
ans=tmp;
ansc=c;ansh=h;
}
}
}
if(~ans) printf("%d %d %d\n",ans,ansc,ansh);
else puts("mission failed");
return 0;
}