Java 用BFS做迷宫?
我一直试图通过广度优先搜索来解决这个问题,但我无法获得所有正确的测试用例,我认为问题在于,它只会计算到最后的直接最短路径,它会计算任何打开的糖果,但不会计算通过糖果的最短路径。代码如下Java 用BFS做迷宫?,java,Java,我一直试图通过广度优先搜索来解决这个问题,但我无法获得所有正确的测试用例,我认为问题在于,它只会计算到最后的直接最短路径,它会计算任何打开的糖果,但不会计算通过糖果的最短路径。代码如下 import java.io.*; import java.util.*; public class HalloweenCandy { static int n, candy; static int minsteps, maxcandy; static int totCandies=0
import java.io.*;
import java.util.*;
public class HalloweenCandy {
static int n, candy;
static int minsteps, maxcandy;
static int totCandies=0;
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("C:\\Users\\Daniel\\Desktop\\Java\\HalloweenCandy\\src\\halloweencandy\\DATA5.txt"));
while (s.hasNext()) {
n=Integer.parseInt(s.nextLine().trim());
char[][]maze=new char[n][n];
int xStart =0;
int yStart =0;
for(int y=0;y<n;++y){
String text = s.nextLine().trim();
for(int x=0;x<n;++x){
maze[x][y]=text.charAt(x);
if(maze[x][y]=='B'){
xStart=x;
yStart=y;
}
}
}
candy=0;
minsteps=0;
BFS(maze,xStart,yStart);
System.out.println(candy+" "+minsteps);
}
}
public static void BFS(char[][]maze,int xStart,int yStart){
Queue<int[]>queue=new LinkedList<int[]>();
int start[]={xStart,yStart,0,0};
queue.add(start);
while(queue.peek()!=null){
int[]array=queue.poll();
int x=array[0];int y=array[1];
if(x<0||y<0||y>n-1||x>n-1)continue;
if(maze[x][y]=='#')continue;
if(maze[x][y]=='*'){
candy++;
minsteps=array[2];
maze[x][y]='.';
}
if(maze[x][y]>='a'&&maze[x][y]<='f'){
if(candy <maze[x][y]-'a'+1)continue;
}
int[][]points = {{0,1},{1,0},{-1,0},{0,-1}};
for(int i=0;i<4;++i){
int sta[]={x+points[i][0],y+points[i][1],array[2]+1};
queue.add(sta);
}
maze[x][y]='#';
}
}
}
import java.io.*;
导入java.util.*;
公开课{
静态int n,candy;
静态int minsteps,maxcandy;
静态int-totCandies=0;
公共静态void main(字符串[]args)引发FileNotFoundException{
Scanner s=new Scanner(新文件(“C:\\Users\\Daniel\\Desktop\\Java\\hallowencandy\\src\\hallowencandy\\DATA5.txt”);
而(s.hasNext()){
n=Integer.parseInt(s.nextLine().trim());
字符[][]迷宫=新字符[n][n];
int xStart=0;
int-yStart=0;
对于(int y=0;y,您正处于写入轨道上,但您错过了一些重要的内容
while(queue.peek()!=null){
int[]array=queue.poll();
int x=array[0];int y=array[1];
if(x<0||y<0||y>n-1||x>n-1)continue;
if(maze[x][y]=='#')continue;
if(maze[x][y]=='*'){
candy++;
minsteps=array[2];
maze[x][y]='.';
}
if(maze[x][y]>='a'&&maze[x][y]<='f'){
if(candy <maze[x][y]-'a'+1)continue;
}
int[][]points = {{0,1},{1,0},{-1,0},{0,-1}};
for(int i=0;i<4;++i){
int sta[]={x+points[i][0],y+points[i][1],array[2]+1};
queue.add(sta);
}
maze[x][y]='#'; // <== this part is wrong
}
这样,一旦你捡起一块新的糖果,正方形就可以再次使用了
然而,这里仍然存在一个问题。想想BFS在这张地图上是如何工作的:
3
...
*B*
...
如果[0,0]是左上角的分幅,则BFS算法将按以下顺序访问分幅:[1,2]、[2,1]、[0,1]、[1,0].怎么了?比利在他相邻的方格之间跳来跳去!你真正想让他做的是每次他得到一块新的糖果时重新启动BFS。我把这部分留给你去弄清楚怎么做
编辑
以下是您希望遵循的基本算法:
从start
位置开始
使用BFS搜索最近的糖果。使用BFS找到的第一块糖果是最近的(或并列为最近的)
在找到一块糖果后,你需要找到离你当前位置最近的下一块,因此将你的当前位置视为另一个BFS的新的start
我刚刚用你的方式解决了,这里的“贪婪”方式就是代码
import java.io.*;
import java.util.*;
public class HalloweenCandy {
static int n, candy;
static int minsteps, maxcandy;
static int totCandies = 0;
static boolean[][] is;
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("C:\\Users\\Daniel\\Desktop\\Java\\HalloweenCandy\\src\\halloweencandy\\DATA5.txt"));
while (s.hasNext()) {
n = Integer.parseInt(s.nextLine().trim());
char[][] maze = new char[n][n];
is = new boolean[n][n];
int xStart = 0;
int yStart = 0;
for (int y = 0; y < n; ++y) {
String text = s.nextLine().trim();
for (int x = 0; x < n; ++x) {
maze[x][y] = text.charAt(x);
if (maze[x][y] == 'B') {
xStart = x;
yStart = y;
}
}
}
candy = 0;
int tot = 0;
int y = 0, x = 0;
x = xStart;
y = yStart;
for (int j = 0; j < n; ++j) {
for (int i = 0; i < n; ++i) {
is[i][j] = false;
}
}
while (true) {
char[][] grid = new char[n][n];
for (int j = 0; j < n; ++j) {
for (int i = 0; i < n; ++i) {
grid[i][j] = maze[i][j];
}
}
int lol[] = BFS(grid, x, y);
if (lol[0] == -1) {
break;
}
y = lol[2];
x = lol[1];
tot += lol[0];
}
System.out.println(candy + " " + tot);
}
}
public static int[] BFS(char[][] maze, int xStart, int yStart) {
Queue<int[]> queue = new LinkedList<int[]>();
int start[] = {xStart, yStart, 0, 0};
queue.add(start);
while (queue.peek() != null) {
int[] array = queue.poll();
int x = array[0];
int y = array[1];
if (x < 0 || y < 0 || y > n - 1 || x > n - 1) {
continue;
}
if (maze[x][y] == '#') {
continue;
}
if (maze[x][y] == '*' && !is[x][y]) {
is[x][y] = true;
candy++;
int sta[] = {array[2], x, y};
return sta;
}
if (maze[x][y] >= 'a' && maze[x][y] <= 'f') {
if (candy < maze[x][y] - 'a' + 1) {
continue;
}
}
int[][] points = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
for (int i = 0; i < 4; ++i) {
int sta[] = {x + points[i][0], y + points[i][1], array[2] + 1};
queue.add(sta);
}
maze[x][y] = '#';
}
int sta[] = {-1};
return sta;
}
}
import java.io.*;
导入java.util.*;
公开课{
静态int n,candy;
静态int minsteps,maxcandy;
静态int-totCandies=0;
静态布尔值[][]为;
公共静态void main(字符串[]args)引发FileNotFoundException{
Scanner s=new Scanner(新文件(“C:\\Users\\Daniel\\Desktop\\Java\\hallowencandy\\src\\hallowencandy\\DATA5.txt”);
而(s.hasNext()){
n=Integer.parseInt(s.nextLine().trim());
字符[][]迷宫=新字符[n][n];
is=新布尔值[n][n];
int xStart=0;
int-yStart=0;
对于(int y=0;yn-1 | | x>n-1){
继续;
}
如果(迷宫[x][y]='#'){
继续;
}
如果(迷宫[x][y]='*'&&&!是[x][y]){
是[x][y]=真;
糖果++;
int sta[]={array[2],x,y};
返回sta;
}
如果(maze[x][y]>='a'&&maze[x][y]是一种贪婪的方法?或者你的意思是当你拿到糖果时继续bfs循环?比如[Star,Dot,B,Star,Star,Star,Star]不起作用,顺便说一句,我不能使用星号和点,因为它阻止了一些。因为这样的最佳解决方案是从最左边的星星开始。你是对的。在这种情况下,它更复杂,因为你必须探索所有的糖果抓取顺序排列,并返回一个导致最少步数的。Y实际上,您应该能够使用,因为排列会有重复的子问题。@Panphobia-BTW,您可以键入“code”例如:*.B***
我对动态规划不是很确定,是的,我知道斐波那契动态规划的简化,还有一些其他的,但我真的不知道动态规划的含义是什么,即使使用维基百科,我想我已经用它解决了其他问题,但我不知道非正式和正式的定义我所看到的就是使用数组来存储递归函数必须一次又一次生成的东西。
import java.io.*;
import java.util.*;
public class HalloweenCandy {
static int n, candy;
static int minsteps, maxcandy;
static int totCandies = 0;
static boolean[][] is;
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("C:\\Users\\Daniel\\Desktop\\Java\\HalloweenCandy\\src\\halloweencandy\\DATA5.txt"));
while (s.hasNext()) {
n = Integer.parseInt(s.nextLine().trim());
char[][] maze = new char[n][n];
is = new boolean[n][n];
int xStart = 0;
int yStart = 0;
for (int y = 0; y < n; ++y) {
String text = s.nextLine().trim();
for (int x = 0; x < n; ++x) {
maze[x][y] = text.charAt(x);
if (maze[x][y] == 'B') {
xStart = x;
yStart = y;
}
}
}
candy = 0;
int tot = 0;
int y = 0, x = 0;
x = xStart;
y = yStart;
for (int j = 0; j < n; ++j) {
for (int i = 0; i < n; ++i) {
is[i][j] = false;
}
}
while (true) {
char[][] grid = new char[n][n];
for (int j = 0; j < n; ++j) {
for (int i = 0; i < n; ++i) {
grid[i][j] = maze[i][j];
}
}
int lol[] = BFS(grid, x, y);
if (lol[0] == -1) {
break;
}
y = lol[2];
x = lol[1];
tot += lol[0];
}
System.out.println(candy + " " + tot);
}
}
public static int[] BFS(char[][] maze, int xStart, int yStart) {
Queue<int[]> queue = new LinkedList<int[]>();
int start[] = {xStart, yStart, 0, 0};
queue.add(start);
while (queue.peek() != null) {
int[] array = queue.poll();
int x = array[0];
int y = array[1];
if (x < 0 || y < 0 || y > n - 1 || x > n - 1) {
continue;
}
if (maze[x][y] == '#') {
continue;
}
if (maze[x][y] == '*' && !is[x][y]) {
is[x][y] = true;
candy++;
int sta[] = {array[2], x, y};
return sta;
}
if (maze[x][y] >= 'a' && maze[x][y] <= 'f') {
if (candy < maze[x][y] - 'a' + 1) {
continue;
}
}
int[][] points = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
for (int i = 0; i < 4; ++i) {
int sta[] = {x + points[i][0], y + points[i][1], array[2] + 1};
queue.add(sta);
}
maze[x][y] = '#';
}
int sta[] = {-1};
return sta;
}
}