走迷宫
前言
抽象模拟赛, 我现在菜的可怕
题面
疑似自出题, 反正不难, 就不找原题了
挂个 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
代码
后补
总结
路径长度类
- 多层图
- dp 加一维状态
注意 DAG 上 dp 可以借助 topu 序处理