洛谷3257 [JLOI2014]天天酷跑(DP)(记忆化搜索)

版权声明:本文为博主原创文章,未经博主允许不得转载,除非先点了赞。 https://blog.csdn.net/A_Bright_CH/article/details/83019789

题目

每次往上跳或往下掉或持平……(具体看题目吧),使路径上的权值和最大。

题解

记忆化搜索
设f[i][j][t]表示从出发点到(x,y)这个位置(不含这个位置,即减掉ma[x][y])还可以跳t次的最大权值和。
转移方程

f[i][j][t]=\max \left\{ f[i+1][j-1][t]+ma[i+1][j-1] , f[i+h][j+h][t-1]+w \right\},其中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;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/83019789