题目内容为一个棋盘,长宽自己输入,棋盘状态自己输入(.表示无棋子,o表示有棋子),可以全部进行上移、下移、左移、右移操作,遇到边界棋子丢失,计算出最短步数使棋盘上仅剩下k个棋子。
import java.util.*;
public class BFS {
public static int n = 0;
public static int m = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String[] strs = s.split(" ");
n = Integer.parseInt(strs[0]);
m = Integer.parseInt(strs[1]);
char[][] ch = new char[n][m];
for(int i = 0; i < n; i++){
String str = sc.nextLine();
ch[i] = str.toCharArray();
}
int k = sc.nextInt();
System.out.print(bfs(ch,k));
}
public static int bfs(char[][] ch, int k){
int currentK = count(ch);
if(currentK < k)
return -1;
if(currentK == k)
return 0;
Queue<char[][]> queue = new ArrayDeque<>();
int step = 0;
queue.offer(ch);
Queue<Integer> q = new ArrayDeque<>();
Set<char[][]> set = new HashSet<>();
set.add(ch);
q.add(step);
while(!queue.isEmpty()){
char[][] current = queue.poll();
int num = count(current);
step = q.poll();
if(num == k){
return step;
}
//expand
step++;
char[][] upChar = up(current);
currentK = count(upChar);
if(currentK >= k && !set.contains(upChar)){
queue.offer(upChar);
q.offer(step);
set.add(upChar);
}
char[][] downChar = down(current);
currentK = count(downChar);
if(currentK >= k && !set.contains(downChar)){
queue.offer(downChar);
q.offer(step);
set.add(downChar);
}
char[][] leftChar = left(current);
currentK = count(leftChar);
if(currentK >= k && !set.contains(leftChar)){
queue.offer(leftChar);
q.offer(step);
set.add(leftChar);
}
char[][] rightChar = right(current);
currentK = count(rightChar);
if(currentK >= k && !set.contains(rightChar)){
queue.offer(rightChar);
q.offer(step);
set.add(rightChar);
}
}
return -1;
}
public static char[][] up(char[][] ch){
char[] tmp = {'.','.','.','.'};
char[][] res = new char[n][m];
for(int i = 0; i < n-1; i++){
res[i] = ch[i+1];
}
res[n-1] = tmp;
return res;
}
public static char[][] down(char[][] ch){
char[] tmp = {'.','.','.','.'};
char[][] res = new char[n][m];
for(int i = n-1; i > 0; i--){
res[i] = ch[i-1];
}
res[0] = tmp;
return res;
}
public static char[][] left(char[][] ch){
char[][] res = new char[n][m];
for(int j = 0; j < m-1; j++){
for(int i = 0; i < n; i++){
res[i][j] = ch[i][j+1];
}
}
for(int i = 0; i < n; i++){
res[i][m-1] = '.';
}
return res;
}
public static char[][] right(char[][] ch){
char[] tmp = {'.','.','.','.'};
char[][] res = new char[n][m];
for(int j = m-1; j > 0; j--){
for(int i = 0; i < n; i++){
res[i][j] = ch[i][j-1];
}
}
for(int i = 0; i < n; i++){
res[i][0] = '.';
}
return res;
}
public static int count(char[][] ch){
int cnt = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(ch[i][j] == 'o')
cnt++;
}
}
return cnt;
}
}