欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【CSP-S膜你考】那23个路口

程序员文章站 2023-11-08 16:11:22
那23个路口 题面 故事的起源不加赘述,那23个路口。 单刀直入,我直接说题的意思。 蚊子和疯子在做一件事,就是他们要在茫茫的大街上找一个出发点,然后从出发点开始,经过上下左右23次拐弯,到达一个他们也不知道的地方。 老城的街道排列的十分有规律,于是疯子和蚊子把老城的街道排布画在了一张地图上。地图上 ......

那23个路口

题面

故事的起源不加赘述,那23个路口。
单刀直入,我直接说题的意思。
蚊子和疯子在做一件事,就是他们要在茫茫的大街上找一个出发点,然后从出发点开始,经过上下左右23次拐弯,到达一个他们也不知道的地方。
老城的街道排列的十分有规律,于是疯子和蚊子把老城的街道排布画在了一张地图上。地图上每一个点代表一个地方,而这个地方有一定的憧憬值,疯子希望可以带蚊子走过的二十三个路口的憧憬值总和是所有方案中最大的。
现在我们读入一个矩阵,如果此点为0,则这个点为起点,如果此点为-1,则这个点为障碍点,否则这个数代表憧憬值。注意起点和障碍点是没有憧憬值的,起点只有开始的时候可以达到,不可以再回来。而障碍点根本就不可以走过。这样一来,请你选择合适的路线,使走完23个路口后得到最大的憧憬值,有憧憬值的点可以重复进出,每次可以选择四个方向,上下左右。起点为第0个路口

输入格式

第1行两个整数 n,m (茫茫大街的长和宽)

第2行到第m+1行,每行n个整数$a_{ij}$(第i行第j个地点的憧憬值)

输出格式

一个整数sum (可以得到的最大憧憬值)

样例

$\texttt{input#1}$
4 4
1 1 1 1
1 1 0 1
1 1 1 1
1 1 1 1

$\texttt{output#1}$
23

数据范围与提示

于30%的数据,$n,m \leqslant 50$

0<n,m<300,每个点的憧憬值可以用longint表示。


题解

dp。f[i][j][k]表示第k步走到(i,j)这个位置的最大憧憬值.则有,

if(map[i][j]<=0) continue;
if(j>1&&map[i][j-1]>=0) f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+map[i][j]);
if(j<m&&map[i][j+1]>=0) f[i][j][k]=max(f[i][j][k],f[i][j+1][k-1]+map[i][j]);
if(i>1&&map[i-1][j]>=0) f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+map[i][j]);
if(i<n&&map[i-1][j]>=0) f[i][j][k]=max(f[i][j][k],f[i+1][j][k-1]+map[i][j]);

$code$

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#define max(a,b) a>b?a:b
#define maxn 301

typedef long long ll;
int n,m;
ll f[maxn][maxn][24],map[maxn][maxn],ans;

inline void read(ll &t) {
    ll x=0;bool f=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    t=f?-x:x;
}

int main() {
    scanf("%d%d",&m,&n);
    memset(f,-0x3f3f3f,sizeof(f));
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=m;++j) {
            read(map[i][j]);
            if(map[i][j]==0) f[i][j][0]=0;
        }
    }
    for(int k=1;k<=23;++k) {
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=m;++j) {
                if(map[i][j]<=0) continue;
                if(j>1&&map[i][j-1]>=0) f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+map[i][j]);
                if(j<m&&map[i][j+1]>=0) f[i][j][k]=max(f[i][j][k],f[i][j+1][k-1]+map[i][j]);
                if(i>1&&map[i-1][j]>=0) f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+map[i][j]);
                if(i<n&&map[i-1][j]>=0) f[i][j][k]=max(f[i][j][k],f[i+1][j][k-1]+map[i][j]);
            }
        }
    }
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=m;++j) {
            if(ans<f[i][j][23]) ans=f[i][j][23];
        }
    }
    std::cout<<ans<<'\n';
    return 0;
}

上接【csp-s膜你考】不怕噩梦 (模拟)