Loading

走迷宫

前言

抽象模拟赛, 我现在菜的可怕

题面

疑似自出题, 反正不难, 就不找原题了
挂个 pdf
题目下载

算法

考虑建图, 如果一个点和相邻点的绝对值 \(= 2\), 则连一条边, 然后就变成了一个 DAG 上 dp 的计数题目。

有向是显然的, 无环是因为 \(a - x \times 2 < a\), 也是显然的 (那我证它干嘛)

于是考虑处理

大小双王走的路径长度(走过的格子个数)必须至少为 \(4\)

多层图

显然为多层图的一种应用

于是复制几遍, 每一次推 dp 从上一层连边推下来即可

细节处理

分层图的建立比较好实现
关于 dp:
建立分层图之后, 正图进行拓扑排序, 记录拓扑序
反图推 dp , 即可

代码

#include <bits/stdc++.h>
#define int long long
const int MAXN = 2e3 + 1;
const int MOD = 1e9 + 7;

#define Calc(x, layers) x + (layers - 1) * n *m

int n, m;
int Map[MAXN][MAXN];

struct node
{
    int to, next;
} Edge[MAXN * MAXN];
int cnt = 0;
int head[MAXN * MAXN];

void init()
{
    for (int i = 1; i <= n * m * 4; i++)
    {
        head[i] = -1;
    }
}

bool InMap(int x, int y)
{
    return 1 <= x && x <= n && 1 <= y && y <= m;
}

void addedge(int u, int v)
{
    Edge[++cnt].to = v;
    Edge[cnt].next = head[u];
    head[u] = cnt;
}

void add_deg(int x_1, int y_1, int x_2, int y_2)
{
    Indeg[Calc((x_2 - 1) * m + y_2, 2)]++;
    Indeg[Calc((x_2 - 1) * m + y_2, 3)]++;
    Indeg[Calc((x_2 - 1) * m + y_2, 4)]++;
    Indeg[Calc((x_2 - 1) * m + y_2, 4)]++;

    OutDeg[Calc((x_1 - 1) * m + y_1, 1)]++;
    OutDeg[Calc((x_1 - 1) * m + y_1, 2)]++;
    OutDeg[Calc((x_1 - 1) * m + y_1, 3)]++;
    OutDeg[Calc((x_1 - 1) * m + y_1, 4)]++;
}

/*建立分层图*/
int Indeg[MAXN * MAXN];
int OutDeg[MAXN * MAXN];
void Make_Gragh()
{
    init();

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            bool HaveRoad = false;
            if (InMap(i, j + 1) && Map[i][j + 1] == Map[i][j] + 2)
            {
                add_deg(i, j, i, j + 1);
                HaveRoad = true;
                addedge(Calc((i - 1) * m + j, 1), Calc((i - 1) * m + j + 1, 2));
                addedge(Calc((i - 1) * m + j, 2), Calc((i - 1) * m + j + 1, 3));
                addedge(Calc((i - 1) * m + j, 3), Calc((i - 1) * m + j + 1, 4));
                addedge(Calc((i - 1) * m + j, 4), Calc((i - 1) * m + j + 1, 4));
            }
            if (InMap(i + 1, j) && Map[i + 1][j] == Map[i][j] + 2)
            {
                add_deg(i, j, i + 1, j);
                HaveRoad = true;
                addedge(Calc((i - 1) * m + j, 1), Calc(i * m + j, 2));
                addedge(Calc((i - 1) * m + j, 2), Calc(i * m + j, 3));
                addedge(Calc((i - 1) * m + j, 3), Calc(i * m + j, 4));
                addedge(Calc((i - 1) * m + j, 4), Calc(i * m + j, 4));
            }
            if (InMap(i - 1, j) && Map[i - 1][j] == Map[i][j] + 2)
            {
                add_deg(i, j, i - 1, j);
                HaveRoad = true;
                addedge(Calc((i - 1) * m + j, 1), Calc((i - 2) * m + j, 2));
                addedge(Calc((i - 1) * m + j, 2), Calc((i - 2) * m + j, 3));
                addedge(Calc((i - 1) * m + j, 3), Calc((i - 2) * m + j, 4));
                addedge(Calc((i - 1) * m + j, 4), Calc((i - 2) * m + j, 4));
            }
            if (InMap(i, j - 1) && Map[i][j - 1] == Map[i][j] + 2)
            {
                add_deg(i, j, i, j - 1);
                HaveRoad = true;
                addedge(Calc((i - 1) * m + j, 1), Calc((i - 1) * m + j - 1, 2));
                addedge(Calc((i - 1) * m + j, 2), Calc((i - 1) * m + j - 1, 3));
                addedge(Calc((i - 1) * m + j, 3), Calc((i - 1) * m + j - 1, 4));
                addedge(Calc((i - 1) * m + j, 4), Calc((i - 1) * m + j - 1, 4));
            }
        }
    }
}


void solve()
{
    /*计算拓扑序*/
}

signed main()
{
    scanf("%lld %lld", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            scanf("%lld", &Map[i][j]);
        }
    }

    Make_Gragh(); // 建图

    solve(); // dp 推可能性

    return 0;
}

/*
5 5
0 2 4 6 8
2 1 6 8 10
4 6 8 10 12
6 8 10 12 14
8 10 12 14 16


30
*/

dp

pAYRaDS.png

代码

后补

总结

路径长度类

  • 多层图
  • dp 加一维状态

注意 DAG 上 dp 可以借助 topu 序处理

posted @ 2024-10-12 17:39  Yorg  阅读(10)  评论(0)    收藏  举报