bfs,分层图,最短路径,牛客小白月赛75-D矩阵
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
现有一个大小为n×mn\times mn×m的二维矩阵,每个元素si,js_{i,j}si,j可能是字符'0'、'1'。
阿宁一开始站在(1,1)(1,1)(1,1),目标走到(n,m)(n,m)(n,m)。
假设当前在(x,y)(x,y)(x,y),一个相邻的位置(x′,y′)(x',y')(x′,y′) ,上下左右 相邻。可以进行以下其中一个行为,花费一个单位时间:
1. 如果sx,ys_{x,y}sx,y是'0',sx′,y′s_{x',y'}sx′,y′是'1',可以从(x,y)(x,y)(x,y)走到(x′,y′)(x',y')(x′,y′)。
2. 如果sx,ys_{x,y}sx,y是'1',sx′,y′s_{x',y'}sx′,y′是'0',可以从(x,y)(x,y)(x,y)走到(x′,y′)(x',y')(x′,y′)。
3. 将sx′,y′s_{x',y'}sx′,y′变成'1'。
4. 将sx′,y′s_{x',y'}sx′,y′变成'0'。
问阿宁从(1,1)(1,1)(1,1)走到(n,m)(n,m)(n,m)需要最少多少单位时间?
输入描述:
第一行输入两个正整数n,mn,mn,m。 接下来输入nnn行,每行mmm个字符,字符仅包含'0'、'1'。 1≤n,m≤10^3
输出描述:
输出一个整数。
这是一道典型的分层图的bfs
分层图:
1、一般用于边或点有特殊限制的问题(如:重复经过多次、多种价值可选)
2、将点拆开,复制多层图,并利用特殊构造的边将各层相连的建图方法
3、需要保证拆开后的总点数规模可接受
这道题建立两层分层图就可以了,只改变下层的点:当要改变点时将目标点下层的点改变,距离加2,然后将该点放入优先队列
注意:这里用的是优先队列,因为它每次加的距离不是一样的了,有时加1,有时加2,因此我们需要用优先队列才能用bfs来处理这种就短距离问题
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
#include<stack>
using namespace std;
typedef long long LL;
const int N = 1e3 + 5;
string str[2][N];
int n, m, v[2][N][N];
int ay[] = { 0,0,1,-1 }, ax[] = { -1,1,0,0 };
typedef struct st {
int c, y, x, d;
}st;
bool operator > (const st& a, const st& b) {
return a.d > b.d;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> str[0][i];
str[0][i].insert(0, " ");
str[1][i] = str[0][i];
}
vector<int>p;
priority_queue<st, vector<st>, greater<st>>q;
q.push({ 0,1,1,0 });
v[0][1][1] = 1;
st t;
while (!q.empty()) {
t = q.top();
q.pop();
//cout << t.c << " " << t.y << " " << t.x << " " << t.d << endl;
if (t.y == n && t.x == m) {
p.push_back(t.d);
if (p.size() == 2)
break;
}
for (int i = 1,y,x; i < 4; i++) {
y = t.y + ay[i];
x = t.x + ax[i];
if (y<1 || y>n || x > m || x < 1)
continue;
if (str[0][y][x] == str[t.c][t.y][t.x]) {
if (v[1][y][x] == 0) {
v[1][y][x] = 1;
if (str[0][y][x] == '1')
str[1][y][x] = '0';
else
str[1][y][x] = '1';
q.push({ 1,y,x,t.d + 2 });
}
continue;
}
if (v[0][y][x] == 1)
continue;
v[0][y][x] = 1;
q.push({ 0,y,x,t.d + 1 });
}
}
sort(p.begin(), p.end());
cout << p[0] << endl;
return 0;
}
这里再补充另一个分层图的做法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N = 1e3 + 5;
int n, m;
string str[N];
int d[N][N][3], v[N][N][3];
int ay[4] = { 0,0,-1,1 }, ax[] = {1,-1,0,0};
typedef struct st {
int y, x, c;
}st;
int bfs() {
memset(d, 0x3f, sizeof(d));
d[1][1][0] = 0;
v[1][1][0] = 1;
queue<st>q;
q.push({ 1,1,0 });
int y, x,c;
while (!q.empty()) {
y = q.front().y;
x = q.front().x;
c = q.front().c;
q.pop();
if (c == 2) {
if (v[y][x][1] == 0) {
d[y][x][1] = d[y][x][2] + 1;
v[y][x][1] = 1;
q.push({ y,x,1 });
}
}
else {
for (int i = 0; i < 4; i++) {
int ty = y + ay[i], tx = x + ax[i];
if (ty<1 || ty>n || tx<1 || tx>m)continue;
if (c == 0) {
if (str[ty][tx] == str[y][x]) {
if (v[ty][tx][2] == 0) {
d[ty][tx][2] = d[y][x][0] + 1;
v[ty][tx][2] = 1;
q.push({ ty,tx,2 });
}
}
else {
if (v[ty][tx][0] == 0) {
d[ty][tx][0] = d[y][x][0] + 1;
v[ty][tx][0] = 1;
q.push({ ty,tx,0 });
}
}
}
else {
if (str[ty][tx] == str[y][x]) {
if (v[ty][tx][0] == 0) {
d[ty][tx][0] = d[y][x][1] + 1;
v[ty][tx][0] = 1;
q.push({ ty,tx,0 });
}
}
else {
if (v[ty][tx][2] == 0) {
d[ty][tx][2] = d[y][x][1] + 1;
v[ty][tx][2] = 1;
q.push({ ty,tx,2 });
}
}
}
}
}
}
return min(d[n][m][0],d[n][m][1]);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
cin >> str[i];
str[i].insert(0, " ");
}
int ans=bfs();
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】