1、矩阵距离
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 1010, M = N * N;
int n, m;
char g[N][N];
PII q[M];
int dist[N][N];
void bfs()
{
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
memset(dist, -1, sizeof dist);
int hh = 0, tt = -1;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
if (g[i][j] == '1')
{
dist[i][j] = 0;
q[ ++ tt] = {i, j};
}
while (hh <= tt)
{
auto t = q[hh ++ ];
for (int i = 0; i < 4; i ++ )
{
int a = t.x + dx[i], b = t.y + dy[i];
if (a < 1 || a > n || b < 1 || b > m) continue;
if (dist[a][b] != -1) continue;
dist[a][b] = dist[t.x][t.y] + 1;
q[ ++ tt] = {a, b};
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%s", g[i] + 1);
bfs();
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ ) printf("%d ", dist[i][j]);
puts("");
}
return 0;
}
2、魔板
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <queue>
using namespace std;
//涉及到get和set 使用char方便操作
char g[2][4];
unordered_map<string, pair<char, string>> pre;
unordered_map<string, int> dist;
void set(string state)
{
for (int i = 0; i < 4; i ++ ) g[0][i] = state[i];
for (int i = 7, j = 0; j < 4; i --, j ++ ) g[1][j] = state[i];
}
string get()
{
string res;
for (int i = 0; i < 4; i ++ ) res += g[0][i];
for (int i = 3; i >= 0; i -- ) res += g[1][i];
return res;
}
string move0(string state)
{
set(state);
for (int i = 0; i < 4; i ++ ) swap(g[0][i], g[1][i]);
return get();
}
string move1(string state)
{
set(state);
int v0 = g[0][3], v1 = g[1][3];
for (int i = 3; i >= 0; i -- )
{
g[0][i] = g[0][i - 1];
g[1][i] = g[1][i - 1];
}
g[0][0] = v0, g[1][0] = v1;
return get();
}
string move2(string state)
{
set(state);
char v = g[0][1];
g[0][1] = g[1][1];
g[1][1] = g[1][2];
g[1][2] = g[0][2];
g[0][2] = v;
return get();
}
int bfs(string start, string end)
{
if (start == end) return 0;
queue<string> q;
q.push(start);
dist[start] = 0;
while (!q.empty())
{
auto t = q.front();
q.pop();
string m[3];
m[0] = move0(t);
m[1] = move1(t);
m[2] = move2(t);
for (int i = 0; i < 3; i ++ )
if (!dist.count(m[i]))
{
dist[m[i]] = dist[t] + 1;
pre[m[i]] = {'A' + i, t};
q.push(m[i]);
if (m[i] == end) return dist[end];
}
}
return -1;
}
int main()
{
int x;
string start, end;
for (int i = 0; i < 8; i ++ )
{
cin >> x;
end += char(x + '0');
}
for (int i = 1; i <= 8; i ++ ) start += char('0' + i);
int step = bfs(start, end);
cout << step << endl;
string res;
while (end != start)
{
res += pre[end].first;
end = pre[end].second;
}
reverse(res.begin(), res.end());
if (step > 0) cout << res << endl;
return 0;
}
3、电路维修
dijkstra可以做
点的坐标
字符的坐标
int bfs()
{
deque q;
}
/*
双端对列广搜:能走通的设置为0,走不通需要转化的设置为1.形成一个边权为0和1的无向图
当遍历到0时,将0放到队首。遍历到1时,将1放到队尾。
本问题可以视为使用双端队列解决特殊的dijstra问题。不是bfs问题。
一般bfs问题,所有的点只能遍历一次,在入队时,确定最小值。
对于本问题是,所有的点可以被遍历很多次,在出队时,决定最小值。
*/
#include <cstring>
#include <iostream>
#include <algorithm>
#include <deque>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 510, M = N * N;
int n, m;
char g[N][N];
//因为是dijsktra算法
//需要距离 和判重数组
int dist[N][N];
//判重数组是,防止使用一个点多次更新到其它点的距离
//模仿dijsktra
bool st[N][N];
int bfs()
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[0][0] = 0;
deque<PII> q;
q.push_back({0, 0});
//按字符坐标 得到格子中的字符
// \\转义字符 需要打2个
char cs[] = "\\/\\/";
//周围的点
int dx[4] = {-1, -1, 1, 1}, dy[4] = {-1, 1, 1, -1};
//周围格子中的字符坐标
int ix[4] = {-1, -1, 0, 0}, iy[4] = {-1, 0, 0, -1};
while (q.size())
{
PII t = q.front();
q.pop_front();
//模仿在dijsktra中 扩展一个点到周围点的最小距离
//出队时,这个点的dist是最小值
if (st[t.x][t.y]) continue;
st[t.x][t.y] = true;
for (int i = 0; i < 4; i ++ )
{
int a = t.x + dx[i], b = t.y + dy[i];
//格点的长度比格子的长度多1.
//格子的长度是(0,0)-(n-1,m-1)
//格点是(0,0)-(n,m)
if (a < 0 || a > n || b < 0 || b > m) continue;
//格子中字符
int ca = t. x + ix[i], cb = t.y + iy[i];
//g[ca][cb]真实格子中的字符 cs[i] 以t这个点向a,b走,需要格子字符的走向
//相同 不加,不同则+1
int d = dist[t.x][t.y] + (g[ca][cb] != cs[i]);
if (d <dist[a][b])
{
dist[a][b] = d;
//边权为1 插入到队尾
if (g[ca][cb] != cs[i]) q.push_back({a, b});
//边权为0 插入到队头
else q.push_front({a, b});
}
}
}
return dist[n][m];
}
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);
int t = bfs();
if (t == 0x3f3f3f3f) puts("NO SOLUTION");
else printf("%d\n", t);
}
return 0;
}