蓝桥杯的大胖子走迷宫,先是尝试了回溯法,应该是由于递归太低效所以算不出结果,先贴上代码。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
//DFS递归低效内存溢出,改成非递归试试
public class FattyMaze {
static int n;
static char[][] maze;
static int [][] temp;
static int move[][]={{0,1},{1,0},{0,-1},{-1,0}};
static int k;
static ArrayList<Integer> li;
public static void main(String[] args) {
li=new ArrayList<Integer>();
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
k=sc.nextInt();
sc.nextLine();
temp=new int[n][n];
for(int i=0;i<temp.length;i++) {
for(int j=0;j<temp[i].length;j++) {
temp[i][j]=0;
}
}
maze=new char[n][n];
for(int i=0;i<n;i++) {
maze[i]=sc.nextLine().toCharArray();
}
sc.close();
for(int i=0;i<maze.length;i++) {
for(int j=0;j<maze[i].length;j++) {
System.out.print(maze[i][j]);
}
System.out.println();
}
int t=0,i=2,j=2;
temp[0][0]=1;
fattyMaze(i,j,t);
System.out.println(Collections.min(li));
}
public static void fattyMaze(int i,int j,int t) {
if(i==n-3&&j==n-3) {
li.add(t);
return;
}
for(int m=0;m<4;m++) {
int t1=t;
int ii=i+move[m][0];
int jj=j+move[m][1];
if(ii>=0&&ii<n&&jj>=0&&jj<n&&maze[ii][jj]=='+'&&temp[ii][jj]==0) {
while(vol(ii,jj,t1++));
temp[ii][jj]=1;
fattyMaze(ii,jj,t1);
temp[ii][jj]=0;
}
}
}
public static boolean vol(int i,int j,int t) {
int vol;
if(t<k)
vol=5;
else if(t<2*k)
vol=3;
else
vol=1;
if(vol==1) return true;
if(i-vol/2<0||i+vol/2>n-1||j-vol/2<0||j+vol/2>n-1)
return false;
int ii,jj=j-vol/2;
for( ii=i-vol/2;ii<=i+vol/2;ii++)
for( jj=j-vol/2;jj<=j+vol/2&&maze[ii][jj]!='*';jj++);
if(jj>j+vol/2)
return true;
else
return false;
}
}
在网上看了看,学到了BFS的方法。其中利用HashMap集合防止重复是我没想到的。
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
//BFS
public class Fatty {
static char[][] maze;
static int k;
static int n;
static int move[][]= {{1,0},{0,1},{-1,0},{0,-1}};
static int t=0;
static HashMap<String,Integer[]> map=new HashMap<>();
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
k=sc.nextInt();
sc.nextLine();
maze=new char[n][n];
for(int i=0;i<n;i++) {
int sum=0;
maze[i]=sc.nextLine().toCharArray();
}
sc.close();
map.put("2,2",new Integer[] {2,2});
fatty();
System.out.println(map.size());
System.out.println(t);
}
public static void fatty() {
int sum=0;
while(true) {
Set<String> set0=map.keySet();
Set<String> set=new HashSet<>();
for(String s:set0) {
set.add(s);
}
//这里不能直接用遍历set0来遍历map的原因是,keySet()方法获得的键集是受到映射支持的,即对map的修改可以在set0中反映出来,
//反过来,修改了set0,也可以在map中反映出来,
//可以用指针的概念来理解,keySet()方法返回的是一个指向map中键集的指针,并不是一个新的键集
//在这个遍历中,对map进行了添加元素的操作,即修改了映射,
//从而导致迭代结果不确定,这和不能在迭代器中使用集合自身的删除方法是一样的道理。
for(String s:set) {
Integer[] p=map.get(s);
if(p[0].equals(n-3)&&p[1].equals(n-3)) {
System.out.println(sum);
return;
}
for(int i=0;i<move.length;i++) {
int x=p[0]+move[i][0];
int y=p[1]+move[i][1];
if(x<0||x>n-1||y<0||y>n-1) continue;
if(vol(x,y)) {
sum++;
map.put(x+","+y,new Integer[] {x,y});
}
}
}
t++;
}
}
public static boolean vol(int i,int j) {
int vol=5;
if(t>=k)
vol=3;
if(t>=2*k)
vol=1;
if(i-vol/2<0||i+vol/2>maze.length-1||j-vol/2<0||j+vol/2>maze[0].length-1) return false;
int ii,jj;
a:for(ii=i-vol/2;ii<=i+vol/2;ii++)
for( jj=j-vol/2;jj<=j+vol/2;jj++)
if(maze[ii][jj]=='*') break a;
if(ii>i+vol/2)
return true;
else
return false;
}
}