持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情。
题目描述
Vincenzo 决定制作立方体 IV,但所有预算只够制作一个正方形迷宫。
它是一个完美的迷宫,每个房间都呈正方形,并具有 44 扇门(四个边一边 11 个)。
每个房间里都有一个号码。
一个人只有在下一个房间的号码比当前房间的号码大 11 的情况下,才能从当前房间移动到下一个房间。
现在,Vincenzo 为所有房间分配了唯一的号码(1,2,3,…S21,2,3,…S2)然后将 S2S2 个人放在了迷宫中,每个房间 11 个,其中 SS 是迷宫的边长。
能够移动次数最多的人将获胜。
弄清楚谁将成为赢家,以及他将能够到达的房间数量。
输入格式
第一行包含整数 TT,表示共有 TT 组测试数据。
每组测试数据第一行包含整数 SS,表示迷宫的边长。
接下来 SS 行,每行包含 SS 个整数,表示具体的迷宫的房间号分布,需注意 1,2,3,…S21,2,3,…S2 这 S2S2 个数字,每个数字只出现一次。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: r d
,其中 xx 是组别编号(从 11 开始),rr 是获胜的人最初所在房间的房间号,dd 是他可以到达的房间数量。
如果有多个人可到达的房间数相同,那么最初所在房间的房间号最小的人将获胜。
数据范围
1≤T≤1001≤T≤100,
1≤S≤10001≤S≤1000
输入样例:
2
2
3 4
1 2
3
1 2 9
5 3 8
4 6 7
输出样例:
Case #1: 1 2
思路
题目的要求是只有下一个房间的房间号比当前房间的房间号大一才可以进入下一个房间 根据数学规律,每个房间都只有唯一路径去其它房间 并且如果当前房间可以到达房间n,那它一定也可以到达房间n可以到达的房间
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
pair<int, int> ans; // 用来记录最后的答案,first是房间号,second是经过的房间数量
int T, s;
int g[N][N], f[N][N]; // g[][]是在i,j处的房间号,f[][]是在i,j处可以进入的房间数
bool st[N][N]; // i,j已经被走过
int dfs(int i, int j)
{
if (st[i][j]) return f[i][j]; // 每个房间有且只有一条可以走的路径,只有唯一的可进入的房间数量
int dx[5] = { 0,-1,0,1 }, dy[5] = { 1,0,-1,0 }; // 上左下右
int road = 0;
for (int k = 0; k < 4; k++)
{
//注意边界情况
if (i + dx[k] <= 0 || i + dx[k] > s || j + dy[k] <= 0 || j + dy[k] > s) continue;
// 如果下一个房间号比当前房间号大一,那这条路径是唯一路径,road记录下一个房间可以到达的房间数量
if (g[i][j] + 1 == g[i + dx[k] ][j + dy[k] ]) road = dfs(i + dx[k], j + dy[k]);
}
st[i][j] = true; // 当前房间已经过
f[i][j] = road + 1; //它自己也算可以经过的房间
return f[i][j];
}
int main()
{
cin >> T;
for (int q = 1 ; q <= T ; q ++)
{
memset(st, 0, sizeof st); // 每次都要把这三个值初始化,否则会出错
memset(f, 0, sizeof f);
ans = { 0 , 0 };
cin >> s;
for (int i = 1; i <= s; i++)
for (int j = 1; j <= s; j++)
scanf("%d", &g[i][j]);
for (int i = 1; i <= s; i++)
for (int j = 1; j <= s; j++)
{
if (st[i][j]) continue; // 当前房间已经通过之前的房间经过了
dfs(i, j); // 找i,j处的房间可以经过的最大房间数量
// 如果i,j处经过的房间数量比答案多或者一样多但是i,j的房间号小
if (f[i][j] > ans.first || f[i][j] == ans.first && g[i][j] < ans.second)
{
ans = { f[i][j], g[i][j] }; // 更新ans的值
}
}
printf("Case #%d: %d %d\n",q , ans.second, ans.first);
}
return 0;
}