NENU 蓝桥杯训练赛(dfs+bfs)
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 k k k 个棋子的所有可行的摆放方案。
dfs时记录当前行、已用棋子个数和列状态(用二进制表示)。
import java.util.*;
import java.math.*;
public class Main {
static char[][] G;
static int n, k, ans;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while((n = cin.nextInt()) != -1 && (k = cin.nextInt()) != -1) {
ans = 0;
G = new char[n][n];
String s;
for(int i = 0;i < n; ++i) {
s = cin.next();
G[i] = s.toCharArray();
}
dfs(0, 0, 0);
System.out.println(ans);
}
cin.close();
}
public static void dfs(int now_row, int sum, int col_status) {
if(sum == k) {
ans++;
return ;
}
if(now_row < n) {
dfs(now_row + 1, sum, col_status);
for(int i = 0;i < n; ++i) {
if(G[now_row][i] == '#' && (col_status & (1 << i)) == 0) {
dfs(now_row + 1, sum + 1, (col_status | (1 << i)));
}
}
}
}
}
三维空间走迷宫。
bfs。
import java.util.*;
import java.math.*;
class pos{
int x, y, z, stp;
pos() {
x = y = z = stp = 0;
}
public void set(int x, int y, int z, int stp) {
this.x = x;
this.y = y;
this.z = z;
this.stp = stp;
}
}
public class Main {
static char[][][] G;
static int[][][] vis;
static int a, b, c;
static int[] dx = {1, -1, 0, 0, 0, 0};
static int[] dy = {0, 0, 1, -1, 0, 0};
static int[] dz = {0, 0, 0, 0, 1, -1};
public static int bfs(pos st, pos ed) {
Queue<pos> q = new LinkedList<pos>();
q.offer(st);
vis[st.x][st.y][st.z] = 1;
pos now;
while((now = q.poll()) != null) {
if(now.x == ed.x && now.y == ed.y && now.z == ed.z) {
return now.stp;
}
for(int i = 0;i < 6; ++i) {
int x = now.x + dx[i];
int y = now.y + dy[i];
int z = now.z + dz[i];
if((x >= 0 && x < a) && (y >= 0 && y < b) && (z >= 0 && z < c) && G[x][y][z] != '#' && vis[x][y][z] == 0) {
pos tmp = new pos();
tmp.set(x, y, z, now.stp + 1);
q.offer(tmp);
vis[x][y][z] = 1;
}
}
}
return Integer.MAX_VALUE;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while((a = cin.nextInt()) != 0 && (b = cin.nextInt()) != 0 && (c = cin.nextInt()) != 0) {
G = new char[a][b][c];
vis = new int[a][b][c];
String s;
pos st = new pos();
pos ed = new pos();
for(int i = 0;i < a; ++i) {
for(int j = 0;j < b; ++j) {
s = cin.next();
G[i][j] = s.toCharArray();
for(int k = 0;k < c; ++k) {
vis[i][j][k] = 0;
if(G[i][j][k] == 'S')st.set(i, j, k, 0);
if(G[i][j][k] == 'E')ed.set(i, j, k, 0);
}
}
}
int ans = bfs(st, ed);
if(ans != Integer.MAX_VALUE) {
System.out.println("Escaped in " + ans + " minute(s).");
}
else {
System.out.println("Trapped!");
}
}
cin.close();
}
}
给定 N , K N,K N,K,问最少对 N N N 进行几次操作可以得到 K K K ?
N , K ∈ [ 0 , 100000 ] N,K \in [0,100000] N,K∈[0,100000] 直接bfs即可, v i s [ i ] vis[i] vis[i] 标记是否到过 i i i 。
import java.util.*;
import java.math.*;
class pos{
int x, stp;
pos(){
x = stp = 0;
}
public void set(int x, int stp) {
this.x = x;
this.stp = stp;
}
}
public class Main {
static int[] vis = new int[100005];
static int n, k;
public static int bfs() {
Queue<pos> q = new LinkedList<pos>();
pos st = new pos();
st.set(n, 0);
q.offer(st);
vis[st.x] = 1;
pos now;
while((now = q.poll()) != null) {
if(now.x == k) {
return now.stp;
}
for(int i = 1;i <= 3; ++i) {
int x = -1;
pos tmp = new pos();
if(i == 1)x = now.x - 1;
if(i == 2)x = now.x + 1;
if(i == 3)x = 2 * now.x;
if((x >= 0 && x <= 100000) && vis[x] == 0) {
tmp.set(x, now.stp + 1);
q.offer(tmp);
vis[x] = 1;
}
}
}
return Integer.MAX_VALUE;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
for(int i = 0;i <= 100000; ++i)vis[i] = 0;
n = cin.nextInt();
k = cin.nextInt();
System.out.println(bfs());
cin.close();
}
}
给你一个 01 01 01 矩阵,矩阵大小为 M × N M \times N M×N 。 ( 1 < = M , N < = 15 ) (1 <= M , N <= 15) (1<=M,N<=15)
每次操作选择一个格子,使得该格子与上下左右四个格子的值翻转。
至少多少次操作可以使得矩阵中所有的值变为 0 0 0 ?
请输出翻转方案,若没有方案,输出" I M P O S S I B L E IMPOSSIBLE IMPOSSIBLE ” 。
暴力枚举第一行的翻转状态,然后判断是否可行。
import java.io.*;
import java.util.*;
import java.math.*;
public class Main{
static int n, m, tmp[][], G[][], res[][], dx[] = {-1, 1, 0, 0, 0}, dy[] = {0, 0, -1, 1, 0};
public static int getcolor(int x, int y) {
int cnt = G[x][y];
for(int i = 0;i <= 4; ++i) {
int xx = x + dx[i], yy = y + dy[i];
if(xx >= 1 && xx <= n && yy >= 1 && yy <= m) {
cnt += tmp[xx][yy];
}
}
return cnt & 1;
}
public static int calc() {
for(int i = 2;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
if(getcolor(i - 1, j) == 1) {
tmp[i][j] = 1;
}
}
}
for(int i = 1; i <= m; ++i) {
if(getcolor(n, i) == 1) {
return Integer.MAX_VALUE;
}
}
int res = 0;
for(int i = 1;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
res += tmp[i][j];
}
}
return res;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
m = cin.nextInt();
G = new int[n + 1][m + 1];
res = new int[n + 1][m + 1];
for(int i = 1;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
G[i][j] = cin.nextInt();
}
}
int ans = Integer.MAX_VALUE;
for(int k = 0;k < (1 << m); ++k) {
tmp = new int[n + 1][m + 1];
for(int j = 1;j <= m; ++j) {
if((k & (1 << (j - 1))) != 0) {
tmp[1][j] = 1;
}
}
int now = calc();
if(now < ans) {
ans = now;
for(int i = 1;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
res[i][j] = tmp[i][j];
}
}
}
}
if(ans == Integer.MAX_VALUE) {
System.out.println("IMPOSSIBLE");
}
else {
for(int i = 1;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
if(j > 1)System.out.print(" ");
System.out.print(res[i][j]);
}
System.out.println();
}
}
}
}
给定一个正整数 n n n ,找出 n n n 的非零倍数 m m m ,其十进制表示形式仅包含数字 0 0 0 和 1 1 1 。
n ∈ [ 1 , 200 ] n \in [1,200] n∈[1,200] ,bfs, v i s [ i ] vis[i] vis[i] 标记是否有数 m o d mod mod n = = i n==i n==i 。
import java.util.*;
import java.math.*;
class num{
BigInteger x;
int re;
public void set(BigInteger x, int re) {
this.x = x;
this.re = re;
}
}
public class Main {
static int vis[] = new int[205];
public static BigInteger calc(BigInteger x, int n) {
for(int i = 0;i <= 200; ++i) {
vis[i] = 0;
}
Queue<num> q = new LinkedList<num>();
if(n == 1) {
return BigInteger.ONE;
}
num fst = new num();
fst.set(BigInteger.ONE, 1);
vis[1] = 1;
q.offer(fst);
num now;
while((now = q.poll()) != null) {
for(int i = 1;i <= 2; ++i) {
num snd = new num();
int now_re = now.re * 10 % n;
if(i == 1) {
if(vis[now_re] == 0) {
vis[now_re] = 1;
snd.set(now.x.multiply(BigInteger.valueOf(10)), now_re);
}
}
else {
now_re = (now_re + 1) % n;
if(vis[now_re] == 0) {
vis[now_re] = 1;
snd.set(now.x.multiply(BigInteger.valueOf(10)).add(BigInteger.ONE), now_re);
}
}
if(snd.x != null) {
if(snd.re == 0) {
return snd.x;
}
q.offer(snd);
}
}
}
return BigInteger.valueOf(-1);
}
public static void test(){
for(int i = 1;i <= 200; ++i) {
System.out.println("a[" + i + "] = \"" + calc(BigInteger.valueOf(i), i) + "\";");
}
System.out.println("END");
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
// test();
String a[] = new String[205];
a[1] = "1";
a[2] = "10";
a[3] = "111";
a[4] = "100";
a[5] = "10";
a[6] = "1110";
a[7] = "1001";
a[8] = "1000";
a[9] = "111111111";
a[10] = "10";
a[11] = "11";
a[12] = "11100";
a[13] = "1001";
a[14] = "10010";
a[15] = "1110";
a[16] = "10000";
a[17] = "11101";
a[18] = "1111111110";
a[19] = "11001";
a[20] = "100";
a[21] = "10101";
a[22] = "110";
a[23] = "110101";
a[24] = "111000";
a[25] = "100";
a[26] = "10010";
a[27] = "1101111111";
a[28] = "100100";
a[29] = "1101101";
a[30] = "1110";
a[31] = "111011";
a[32] = "100000";
a[33] = "111111";
a[34] = "111010";
a[35] = "10010";
a[36] = "11111111100";
a[37] = "111";
a[38] = "110010";
a[39] = "10101";
a[40] = "1000";
a[41] = "11111";
a[42] = "101010";
a[43] = "1101101";
a[44] = "1100";
a[45] = "1111111110";
a[46] = "1101010";
a[47] = "10011";
a[48] = "1110000";
a[49] = "1100001";
a[50] = "100";
a[51] = "100011";
a[52] = "100100";
a[53] = "100011";
a[54] = "11011111110";
a[55] = "110";
a[56] = "1001000";
a[57] = "11001";
a[58] = "11011010";
a[59] = "11011111";
a[60] = "11100";
a[61] = "100101";
a[62] = "1110110";
a[63] = "1111011111";
a[64] = "1000000";
a[65] = "10010";
a[66] = "1111110";
a[67] = "1101011";
a[68] = "1110100";
a[69] = "10000101";
a[70] = "10010";
a[71] = "10011";
a[72] = "111111111000";
a[73] = "10001";
a[74] = "1110";
a[75] = "11100";
a[76] = "1100100";
a[77] = "1001";
a[78] = "101010";
a[79] = "10010011";
a[80] = "10000";
a[81] = "1111111101";
a[82] = "111110";
a[83] = "101011";
a[84] = "1010100";
a[85] = "111010";
a[86] = "11011010";
a[87] = "11010111";
a[88] = "11000";
a[89] = "11010101";
a[90] = "1111111110";
a[91] = "1001";
a[92] = "11010100";
a[93] = "10000011";
a[94] = "100110";
a[95] = "110010";
a[96] = "11100000";
a[97] = "11100001";
a[98] = "11000010";
a[99] = "111111111111111111";
a[100] = "100";
a[101] = "101";
a[102] = "1000110";
a[103] = "11100001";
a[104] = "1001000";
a[105] = "101010";
a[106] = "1000110";
a[107] = "100010011";
a[108] = "110111111100";
a[109] = "1001010111";
a[110] = "110";
a[111] = "111";
a[112] = "10010000";
a[113] = "1011011";
a[114] = "110010";
a[115] = "1101010";
a[116] = "110110100";
a[117] = "10101111111";
a[118] = "110111110";
a[119] = "100111011";
a[120] = "111000";
a[121] = "11011";
a[122] = "1001010";
a[123] = "10001100111";
a[124] = "11101100";
a[125] = "1000";
a[126] = "11110111110";
a[127] = "11010011";
a[128] = "10000000";
a[129] = "100100001";
a[130] = "10010";
a[131] = "101001";
a[132] = "11111100";
a[133] = "11101111";
a[134] = "11010110";
a[135] = "11011111110";
a[136] = "11101000";
a[137] = "10001";
a[138] = "100001010";
a[139] = "110110101";
a[140] = "100100";
a[141] = "10011";
a[142] = "100110";
a[143] = "1001";
a[144] = "1111111110000";
a[145] = "11011010";
a[146] = "100010";
a[147] = "1100001";
a[148] = "11100";
a[149] = "110111";
a[150] = "11100";
a[151] = "1110001";
a[152] = "11001000";
a[153] = "10111110111";
a[154] = "10010";
a[155] = "1110110";
a[156] = "1010100";
a[157] = "10101101011";
a[158] = "100100110";
a[159] = "100011";
a[160] = "100000";
a[161] = "11101111";
a[162] = "11111111010";
a[163] = "1010111";
a[164] = "1111100";
a[165] = "1111110";
a[166] = "1010110";
a[167] = "11111011";
a[168] = "10101000";
a[169] = "10111101";
a[170] = "111010";
a[171] = "1111011111";
a[172] = "110110100";
a[173] = "1011001101";
a[174] = "110101110";
a[175] = "100100";
a[176] = "110000";
a[177] = "100101111";
a[178] = "110101010";
a[179] = "11010111";
a[180] = "11111111100";
a[181] = "1001111";
a[182] = "10010";
a[183] = "100101";
a[184] = "110101000";
a[185] = "1110";
a[186] = "100000110";
a[187] = "1001011";
a[188] = "1001100";
a[189] = "1010111010111";
a[190] = "110010";
a[191] = "11101111";
a[192] = "111000000";
a[193] = "11001";
a[194] = "111000010";
a[195] = "101010";
a[196] = "110000100";
a[197] = "1101000101";
a[198] = "1111111111111111110";
a[199] = "111000011";
a[200] = "1000";
while(cin.hasNext()) {
int n = cin.nextInt();
if(n == 0)break;
else {
System.out.println(a[n]);
}
}
cin.close();
}
}
给定两个四位的素数 a , b a,b a,b 。 a a a 可以改变某一位上的数字变成 c c c ,但只有当 c c c 也是四位的素数时才能进行这种改变。问 a a a 最少经过多少次上述变换才能变成 b b b ?
bfs, v i s [ i ] vis[i] vis[i] 标记四位素数 i i i 是否出现过。
import java.io.*;
import java.util.*;
import java.math.*;
class num{
int x,stp;
num(){
x = stp = 0;
}
public void set(int x, int stp) {
this.x = x;
this.stp = stp;
}
}
public class Main{
static int vis[] = new int[100005];
public static boolean isprime(int x) {
if(x == 1)return false;
for(int i = 2;i * i <= x; ++i) {
if(x % i == 0)return false;
}
int i = 0;
for(;i < 4 && x > 0; ++i) {
x /= 10;
}
return i == 4 ? true : false;
}
public static int calc(int st, int ed) {
for(int i = 0;i < 100000; ++i) {
vis[i] = 0;
}
Queue<num> q = new LinkedList<num>();
num fst = new num();
fst.set(st, 0);
vis[st] = 1;
q.offer(fst);
num now;
while((now = q.poll()) != null) {
if(now.x == ed) {
return now.stp;
}
int a[] = new int[5];
int b[] = new int[5];
for(int i = 0;i < 4; ++i) {
a[i] = 0;
}
for(int i = 0, j = now.x;i < 4 && j > 0; ++i, j /= 10) {
a[i] = j % 10;
}
for(int i = 0;i < 4; ++i) {
b[i] = a[i];
}
for(int i = 0;i < 4; ++i) {
for(int j = 0;j < 10; ++j) {
a[i] = j;
num p = new num();
p.x = a[0] + a[1] * 10 + a[2] * 100 + a[3] * 1000;
if(vis[p.x] == 0 && isprime(p.x)) {
p.stp = now.stp + 1;
vis[p.x] = 1;
q.offer(p);
}
}
a[i] = b[i];
}
}
return -1;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t-- > 0) {
int n = cin.nextInt();
int m = cin.nextInt();
int ans = calc(n, m);
System.out.println(ans == -1 ? "Impossible" : ans);
}
}
}
给定两个长度为 n n n 的字符串 s 1 s1 s1 和 s 2 s2 s2 , 接着给出一个长度为 2 n 2n 2n 的字符串 s s s 。问将字符串 s 1 s1 s1 和 s 2 s2 s2 通过一定的变换变成 s s s 需要几次变换次数?
变换规则如下:
假设 s 1 = 12345 , s 2 = 67890 s1=12345,s2=67890 s1=12345,s2=67890
变换后的序列 s 12 = 6172839405 s12=6172839405 s12=6172839405
如果 s 12 s12 s12 和 s s s 完全相等那么输出变换次数
如果不完全相等, s s s 的前半部分作为 s 1 s1 s1 ,后半部分作为 s 2 s2 s2 ,重复上述过程。
模拟,变换 1000 1000 1000 次有解输出,无解输出 − 1 -1 −1 。
import java.io.*;
import java.util.*;
public class Main{
static char a1[], a2[] = new char[205];
public static String calc(String s1, String s2, int n) {
String res = "";
for(int i = 0;i < n; ++i) {
res += s2.charAt(i);
res += s1.charAt(i);
}
return res.toString();
}
public static boolean check(String s1, String s2, int n) {
for(int i = 0;i < n; ++i) {
if(s1.charAt(i) != s2.charAt(i))return false;
}
return true;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
for(int ca = 1;ca <= t; ++ca) {
int n = cin.nextInt();
String s1, s2, s;
s1 = cin.next();
s2 = cin.next();
s = cin.next();
int f = 0;
for(int i = 1;i <= 1000; ++i) {
String nows = calc(s1, s2, n);
s1 = nows.substring(0, n);
s2 = nows.substring(n, 2 * n);
if(check(nows, s, 2 * n)) {
System.out.println(ca + " " + i);
f = 1;
break;
}
}
if(f == 0) {
System.out.println(ca + " " + -1);
}
}
}
}
小明给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作:
问最少操作数使其中任何一个容器里的水恰好有C升并给出操作过程。
bfs + 分类讨论, v i s [ x ] [ y ] vis[x][y] vis[x][y] 表示到达第一个杯子 x x x 升水,第二个杯子 y y y 升水的最少操作数,用 p r e [ x ] [ y ] pre[x][y] pre[x][y] 记录前驱状态。
import java.io.*;
import java.util.*;
import java.math.*;
class cup{
int x,y;
cup(){
x = y = 0;
}
cup(int x, int y){
this.x = x;
this.y = y;
}
public void set(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main{
static int vis[][];
static String s[][];
static cup pre[][], ed;
public static int calc(int A, int B, int C) {
for(int i = 0;i <= A; ++i) {
for(int j = 0;j <= B; ++j) {
vis[i][j] = 0;
}
}
Queue<cup> q = new LinkedList<cup>();
q.offer(new cup(0, 0));
vis[0][0] = 1;
cup now;
while((now = q.poll()) != null) {
int x = now.x, y = now.y;
if(x == C || y == C) {
ed = new cup(x, y);
return vis[x][y];
}
//fill 1
if(x != A) {
if(vis[A][y] == 0) {
vis[A][y] = vis[x][y] + 1;
s[A][y] = "FILL(1)";
pre[A][y] = new cup(x, y);
q.offer(new cup(A, y));
}
}
//fill 2
if(y != B) {
if(vis[x][B] == 0) {
vis[x][B] = vis[x][y] + 1;
s[x][B] = "FILL(2)";
pre[x][B] = new cup(x, y);
q.offer(new cup(x, B));
}
}
//drop 1
if(x != 0) {
if(vis[0][y] == 0) {
vis[0][y] = vis[x][y] + 1;
s[0][y] = "DROP(1)";
pre[0][y] = new cup(x, y);
q.offer(new cup(0, y));
}
}
//drop 2
if(y != 0) {
if(vis[x][0] == 0) {
vis[x][0] = vis[x][y] + 1;
s[x][0] = "DROP(2)";
pre[x][0] = new cup(x, y);
q.offer(new cup(x, 0));
}
}
//1 -> 2
int detal = Math.min(x, B - y);
int nowx = x - detal, nowy = y + detal;
if(vis[nowx][nowy] == 0) {
vis[nowx][nowy] = vis[x][y] + 1;
s[nowx][nowy] = "POUR(1,2)";
pre[nowx][nowy] = new cup(x, y);
q.offer(new cup(nowx, nowy));
}
//2 -> 1
detal = Math.min(A - x, y);
nowx = x + detal;
nowy = y - detal;
if(vis[nowx][nowy] == 0) {
vis[nowx][nowy] = vis[x][y] + 1;
s[nowx][nowy] = "POUR(2,1)";
pre[nowx][nowy] = new cup(x, y);
q.offer(new cup(nowx, nowy));
}
}
return -1;
}
public static void cout(int x, int y) {
if(pre[x][y] == null) {
return ;
}
cout(pre[x][y].x, pre[x][y].y);
System.out.println(s[x][y]);
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int A,B,C;
A = cin.nextInt();
B = cin.nextInt();
C = cin.nextInt();
vis = new int[A + 5][B + 5];
pre = new cup[A + 5][B + 5];
s = new String[A + 5][B + 5];
int ans = calc(A, B, C);
System.out.println(ans == -1 ? "impossible" : ans - 1);
cout(ed.x, ed.y);
}
}
乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。
# \# # 代表墙
. . . 代表空地,火和乔是可通行的
J J J 乔在迷宫中最初的位置,火和乔是可通行的
F F F 代表火
在每组测试中只有一个 J J J 。
bfs,先移动火,再移动人。
import java.io.*;
import java.util.*;
import java.math.*;
class pos{
int x, y, op;
pos(){
x = y = op = 0;
}
pos(int x, int y, int op){
this.x = x;
this.y = y;
this.op = op;
}
public void set(int x, int y, int op) {
this.x = x;
this.y = y;
this.op = op;
}
}
public class Main{
static int n, m, vis1[][], vis2[][], dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
static char G[][];
public static int calc(int x1, int y1) {
Queue<pos> q = new LinkedList<pos>();
for(int i = 1;i <= n; ++i) {
for(int j = 1;j <= m; ++j) {
if(G[i][j] == 'F') {
vis1[i][j] = 1;
q.offer(new pos(i, j, 2));
}
}
}
vis1[x1][y1] = 1;
q.offer(new pos(x1, y1, 1));
pos now;
while((now = q.poll()) != null) {
int x = now.x, y = now.y;
for(int i = 0;i < 4; ++i) {
int xx = x + dx[i], yy = y + dy[i];
if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && G[xx][yy] == '.' && vis1[xx][yy] == 0) {
vis1[xx][yy] = vis1[x][y] + 1;
q.offer(new pos(xx, yy, now.op));
}
if(xx == 0 || xx == n + 1 || yy == 0 || yy == m + 1 && vis1[xx][yy] == 0) {
if(now.op == 1)return vis1[x][y];
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
for(int ca = 1;ca <= t; ++ca) {
n = cin.nextInt();m = cin.nextInt();
vis1 = new int[n + 5][m + 5];
vis2 = new int[n + 5][m + 5];
G = new char[n + 5][m + 5];
String s;
int x1, y1;
x1 = y1 = 0;
for(int i = 1;i <= n; ++i) {
s = cin.next();
for(int j = 1;j <= m; ++j) {
G[i][j] = s.charAt(j - 1);
if(G[i][j] == 'J') {
x1 = i;y1 = j;
}
}
}
int ans = calc(x1, y1);
System.out.println(ans == -1 ? "IMPOSSIBLE" : ans);
}
}
}
一个 5 × 5 5 \times 5 5×5 的二维数组,表示一个迷宫。其中的 1 1 1 表示墙壁, 0 0 0 表示可以走的路,只能横着走或竖着走,不能斜着走,求从左上角到右下角的最短路线。
bfs, v i s [ x ] [ y ] vis[x][y] vis[x][y] 记录步数,用 p r e [ x ] [ y ] pre[x][y] pre[x][y] 记录前驱状态,表示到 ( x , y ) (x,y) (x,y) 的上一步在哪里。
import java.io.*;
import java.util.*;
import java.math.*;
class pos{
int x,y;
pos(){
x = y = 0;
}
public void set(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main{
static int vis[][] = new int[10][10];
static int G[][] = new int[10][10];
static pos pre[][] = new pos[10][10];
static int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0};
public static boolean ck(int x, int y) {
if(x >= 0 && x < 5 && y >= 0 && y < 5 && G[x][y] == 0)return true;
return false;
}
public static void cout(int x, int y) {
if(x == 0 && y == 0) {
System.out.println("(" + x + ", " + y + ")");
return ;
}
cout(pre[x][y].x, pre[x][y].y);
System.out.println("(" + x + ", " + y + ")");
}
public static void calc() {
for(int i = 0;i < 10; ++i) {
for(int j = 0;j < 10; ++j) {
vis[i][j] = 0;
}
}
Queue<pos> q = new LinkedList<pos>();
pos fst = new pos();
fst.set(0, 0);
vis[0][0] = 1;
q.offer(fst);
pos now;
while((now = q.poll()) != null) {
if(now.x == 4 && now.y == 4) {
break;
}
for(int i = 0;i < 4; ++i) {
int xx = now.x + dx[i];
int yy = now.y + dy[i];
if(ck(xx, yy) && vis[xx][yy] == 0) {
vis[xx][yy] = vis[now.x][now.y] + 1;
pre[xx][yy] = now;
pos scnd = new pos();
scnd.set(xx, yy);
q.offer(scnd);
}
}
}
cout(4, 4);
return ;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
for(int i = 0;i < 5; ++i) {
for(int j = 0;j < 5; ++j) {
G[i][j] = cin.nextInt();
}
}
calc();
}
}