踩方格

GitHub跳转原题关系图返回列表

题意与原解析均从本地 OpenJudge 缓存迁移。

OJ: noi_openjudge

题目 ID: ch0206-4982

难度:未知

标签:

日期: 2026-07-30 23:01

题意

完整题面见同目录的 problem.md

思路

解析

就是数字金字塔

可以想到这里就是dfs走迷宫,于是上来就写一个dfs的代码,这个代码可以作为验证数据是否正确.

dp思想

dp第一步,就是分阶段,也就是确定 题目没有后效性,也就是不能"回头",也就是不能回到过去

针对这个题目,显然每上一层,就不能回到下一层了,从层上来说,就符合DP.

假如局限在这一行,显然这个点一旦向右走,就不能回头

错误的代码

考虑的状态不对,没有考虑到,起点上面的格式,可以3步走到

代码

cpp
#include <iostream>
using namespace std;
typedef  long long ll;
int n;

ll f[3][25][55][55];
// f[state][step][x][y]  表示到以state状态到达x,y,且走了step步

// 0 表示从下一层,x-1,到达这一层x层
// 1 表示从左边的点,来到
// 2 表示从右边的点来到

int sx = 1;
int sy = 22;
long long ans;

void print(int a,int b,int c,int d) 
{
    return;
    int t = f[a][b][c][d];
    if( t == 0) return;
    cout << "f[" << a << "]";
    cout << "[" << b << "]";
    cout << "[" << c << "]";
    cout << "[" << d << "]";
    cout << "=" << t << endl;
}


int main() {
    cin >> n;
    f[0][0][sx][sy]=1;

    int st= sy-n;
    int ed= sy+n;

    //i表示到达这一层
    for(int i = 1;i<=n;i++) {
        //枚举step
        for(int step = 1 ;step <= n;++step)
        {

            //枚举 这一层从下一层上来
            for(int j = st; j<=ed;j++) {
                f[0][step][i][j] += f[0][step-1][i][j] + f[1][step-1][i][j] + f[2][step-1][i][j];
                print(0,step,i,j);
            }

            //枚举从左边来
            for(int j = st; j <= ed;j++)
            {
                f[1][step][i][j] += f[0][step-1][i][j-1] + f[1][step-1][i][j-1];
                print(1,step,i,j);
            }
            //枚举从左边来
            for(int j = ed; j >= st;j--)
            {
                f[2][step][i][j] += f[0][step-1][i][j+1] + f[2][step-1][i][j+1];
                print(2,step,i,j);
            }

            for(int j = st; j <= ed;j++)
                if(step == n)
                {
                    ans += f[0][step][i][j];
                    ans += f[1][step][i][j];
                    ans += f[2][step][i][j];
                }
        }
    }
    cout << ans << endl;

    return 0;
}

复杂度

总结