在使用 BFS 到达目的地之前访问网格中的选定点
Visiting Selected Points in a Grid before Reaching a Destination using BFS
好吧,我正在实施一个问题的解决方案,首先是给你一个 (n,n) 网格。它要求我从 (1,1) 开始,访问网格中标记为 * 的某些点,然后最后进行到 (n,n)。网格的大小保证不超过 15,访问的点数 * 保证 >=0 且 <=n-2。起点和终点始终为空。有一些障碍,#我不能踩的地方。此外,如果我在到达某个 * 之前访问过某个点,我可以在收集 * 后再次通过它。
这是我的解决方案的作用。我创建了一个名为 'Node' 的数据结构,它有 2 个整数数据类型 (x,y)。它基本上是一个元组。
class Node
{
int x,y;
Node(int x1,int y1)
{
x=x1;
y=y1;
}
}
在获取网格时,我维护了一个 Set,它存储网格中“*”的坐标。
Set<Node> points=new HashSet<Node>();
我维护了一个网格数组和一个距离数组
char [][]
int distances [][]
现在我要做的是,我将 BFS 应用为 (1,1) 作为源。一旦我遇到任何“*”(我相信这将是最接近的,因为 BFS 为我们提供了未加权图中的最短路径),我将其从集合中删除。
现在我再次应用 BFS,我的源成为找到的“*”的最后一个坐标。每次,我都会刷新距离数组,因为我的源坐标发生了变化。对于网格数组,我为上一次迭代刷新标记为 'V'(已访问)的路径。
整个过程一直持续到我到达最后一个“*”。
顺便说一句,如果我的 BFS returns -1,程序会打印“-1”并退出。
现在,如果我以尽可能短的方式成功到达所有“”(我猜?),我将网格中的 (n,n) 坐标设置为“”最后一次应用 BFS。这样我就到了最后一点。
现在我的解决方案似乎在某处失败了。哪里出错了?我的概念错了吗?这种 'greedy' 方法会失败吗?获得所有“*”检查点之间的最短路径最终应该让我得到最短路径 IMO。
我环顾四周,看到这个问题类似于旅行商问题,也可以通过动态规划和 DFS 混合或 A* 解决 algorithm.I 不知道如何解决。有人甚至在每个 * 之间说 dijkstra,但据我所知,在未加权的图中,Dijktra 和 BFS 的工作原理相同。我只想知道为什么这个 BFS 解决方案失败
最后,这是我的代码:
import java.io.*;
import java.util.*;
/**
* Created by Shreyans on 5/2/2015 at 2:29 PM using IntelliJ IDEA (Fast IO Template)
*/
//ADD PUBLIC FOR CF,TC
class Node
{
int x,y;
Node(int x1,int y1)
{
x=x1;
y=y1;
}
}
class N1
{
//Datastructures and Datatypes used
static char grid[][];
static int distances[][];
static int r=0,c=0,s1=0,s2=0,f1=0,f2=0;
static int dx[]={1,-1,0,0};
static int dy[]={0,0,-1,1};
static Set<Node> points=new HashSet<Node>();
static int flag=1;
public static void main(String[] args) throws IOException
{
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();//testcases
for(int ixx=0;ixx<t;ixx++)
{
flag=1;
r=sc.nextInt();
if(r==1)
{
sc.next();//Taking in '.' basically
System.out.println("0");//Already there
continue;
}
c=r;//Rows guarenteed to be same as rows. It a nxn grid
grid=new char[r][c];
distances=new int[r][c];
points.clear();
for(int i=0;i<r;i++)
{
char[]x1=sc.next().toCharArray();
for(int j=0;j<c;j++)
{
grid[i][j]=x1[j];
if(x1[j]=='*')
{
points.add(new Node(i,j));
}
}
}//built grid
s1=s2=0;
distances[s1][s2]=0;//for 0,0
int ansd=0;
while(!points.isEmpty())
{
for(int i=0;i<r;i++)
{
for (int j = 0; j < c; j++)
{
distances[i][j]=0;
if(grid[i][j]=='V')//Visited
{
grid[i][j]='.';
}
}
}
distances[s1][s2]=0;
int dis=BFS();
if(dis!=-1)
{
ansd += dis;//Adding on (minimum?) distaces
//System.out.println("CURR DIS: "+ansd);
}
else
{
System.out.println("-1");
flag = 0;
break;
}
}
if(flag==1)
{
for(int i11=0;i11<r;i11++)
{
for(int j1=0;j1<c;j1++)
{
if(grid[i11][j1]=='V')//These pnts become accesible in the next iteration again
{
grid[i11][j1]='.';
}
distances[i11][j1]=0;
}
}
f1=r-1;f2=c-1;
grid[f1][f2]='*';
int x=BFS();
if(x!=-1)
{
System.out.println((ansd+x));//Final distance
}
else
{
System.out.println("-1");//Not possible
}
}
}
}
public static int BFS()
{
// Printing current grid correctly according to concept
System.out.println("SOURCE IS:"+(s1+1)+","+(s2+1));
for(int i2=0;i2<r;i2++)
{
for (int j1 = 0; j1 < c; j1++)
{
{
System.out.print(grid[i2][j1]);
}
}
System.out.println();
}
Queue<Node>q=new LinkedList<Node>();
q.add(new Node(s1,s2));
while(!q.isEmpty())
{
Node p=q.poll();
for(int i=0;i<4;i++)
{
if(((p.x+dx[i]>=0)&&(p.x+dx[i]<r))&&((p.y+dy[i]>=0)&&(p.y+dy[i]<c))&&(grid[p.x+dx[i]][p.y+dy[i]]!='#'))
{//If point is in range
int cx,cy;
cx=p.x+dx[i];
cy=p.y+dy[i];
distances[cx][cy]=distances[p.x][p.y]+1;//Distances
if(grid[cx][cy]=='*')//destination
{
for(Node rm:points)// finding the node and removing it
{
if(rm.x==cx&&rm.y==cy)
{
points.remove(rm);
break;
}
}
grid[cx][cy]='.';//It i walkable again
s1=cx;s2=cy;//next source set
return distances[cx][cy];
}
else if(grid[cx][cy]=='.')//Normal tile. Now setting to visited
{
grid[cx][cy]='V';//Adding to visited
q.add(new Node(cx,cy));
}
}
}
}
return -1;
}
}
这是我的几个测试用例的代码。给出正确答案:
JAVA: http://ideone.com/qoE859
C++ : http://ideone.com/gsCSSL
这是我的代码失败的地方:http://www.codechef.com/status/N1,bholagabbar
你的想法是错误的。我没有读过代码,因为你描述的即使完美实现也会失败。
考虑这样的事情:
x....
.....
..***
....*
*...*
您将像这样穿越迷宫:
x....
.....
..123
....4
*...5
然后从 5
到左下 *
并返回 5
,走 16
步。然而,这:
x....
.....
..234
....5
1...6
走 12
步。
问题的正确解法涉及蛮力。生成*
个位置的所有排列,按照排列给出的顺序访问它们,取最小的。
13!
相当大,所以这可能不够快。在 O(2^k)
中有一个更快的动态规划解决方案,类似于 Travelling Salesman Dynamic Programming Solution (also here).
我现在没有时间谈论解决方案。如果您对此有任何疑问,请随时提出另一个问题,我相信有人会插话(或让这个问题保持开放状态)。
好吧,我正在实施一个问题的解决方案,首先是给你一个 (n,n) 网格。它要求我从 (1,1) 开始,访问网格中标记为 * 的某些点,然后最后进行到 (n,n)。网格的大小保证不超过 15,访问的点数 * 保证 >=0 且 <=n-2。起点和终点始终为空。有一些障碍,#我不能踩的地方。此外,如果我在到达某个 * 之前访问过某个点,我可以在收集 * 后再次通过它。
这是我的解决方案的作用。我创建了一个名为 'Node' 的数据结构,它有 2 个整数数据类型 (x,y)。它基本上是一个元组。
class Node
{
int x,y;
Node(int x1,int y1)
{
x=x1;
y=y1;
}
}
在获取网格时,我维护了一个 Set,它存储网格中“*”的坐标。
Set<Node> points=new HashSet<Node>();
我维护了一个网格数组和一个距离数组
char [][]
int distances [][]
现在我要做的是,我将 BFS 应用为 (1,1) 作为源。一旦我遇到任何“*”(我相信这将是最接近的,因为 BFS 为我们提供了未加权图中的最短路径),我将其从集合中删除。
现在我再次应用 BFS,我的源成为找到的“*”的最后一个坐标。每次,我都会刷新距离数组,因为我的源坐标发生了变化。对于网格数组,我为上一次迭代刷新标记为 'V'(已访问)的路径。
整个过程一直持续到我到达最后一个“*”。 顺便说一句,如果我的 BFS returns -1,程序会打印“-1”并退出。
现在,如果我以尽可能短的方式成功到达所有“”(我猜?),我将网格中的 (n,n) 坐标设置为“”最后一次应用 BFS。这样我就到了最后一点。
现在我的解决方案似乎在某处失败了。哪里出错了?我的概念错了吗?这种 'greedy' 方法会失败吗?获得所有“*”检查点之间的最短路径最终应该让我得到最短路径 IMO。
我环顾四周,看到这个问题类似于旅行商问题,也可以通过动态规划和 DFS 混合或 A* 解决 algorithm.I 不知道如何解决。有人甚至在每个 * 之间说 dijkstra,但据我所知,在未加权的图中,Dijktra 和 BFS 的工作原理相同。我只想知道为什么这个 BFS 解决方案失败
最后,这是我的代码:
import java.io.*;
import java.util.*;
/**
* Created by Shreyans on 5/2/2015 at 2:29 PM using IntelliJ IDEA (Fast IO Template)
*/
//ADD PUBLIC FOR CF,TC
class Node
{
int x,y;
Node(int x1,int y1)
{
x=x1;
y=y1;
}
}
class N1
{
//Datastructures and Datatypes used
static char grid[][];
static int distances[][];
static int r=0,c=0,s1=0,s2=0,f1=0,f2=0;
static int dx[]={1,-1,0,0};
static int dy[]={0,0,-1,1};
static Set<Node> points=new HashSet<Node>();
static int flag=1;
public static void main(String[] args) throws IOException
{
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();//testcases
for(int ixx=0;ixx<t;ixx++)
{
flag=1;
r=sc.nextInt();
if(r==1)
{
sc.next();//Taking in '.' basically
System.out.println("0");//Already there
continue;
}
c=r;//Rows guarenteed to be same as rows. It a nxn grid
grid=new char[r][c];
distances=new int[r][c];
points.clear();
for(int i=0;i<r;i++)
{
char[]x1=sc.next().toCharArray();
for(int j=0;j<c;j++)
{
grid[i][j]=x1[j];
if(x1[j]=='*')
{
points.add(new Node(i,j));
}
}
}//built grid
s1=s2=0;
distances[s1][s2]=0;//for 0,0
int ansd=0;
while(!points.isEmpty())
{
for(int i=0;i<r;i++)
{
for (int j = 0; j < c; j++)
{
distances[i][j]=0;
if(grid[i][j]=='V')//Visited
{
grid[i][j]='.';
}
}
}
distances[s1][s2]=0;
int dis=BFS();
if(dis!=-1)
{
ansd += dis;//Adding on (minimum?) distaces
//System.out.println("CURR DIS: "+ansd);
}
else
{
System.out.println("-1");
flag = 0;
break;
}
}
if(flag==1)
{
for(int i11=0;i11<r;i11++)
{
for(int j1=0;j1<c;j1++)
{
if(grid[i11][j1]=='V')//These pnts become accesible in the next iteration again
{
grid[i11][j1]='.';
}
distances[i11][j1]=0;
}
}
f1=r-1;f2=c-1;
grid[f1][f2]='*';
int x=BFS();
if(x!=-1)
{
System.out.println((ansd+x));//Final distance
}
else
{
System.out.println("-1");//Not possible
}
}
}
}
public static int BFS()
{
// Printing current grid correctly according to concept
System.out.println("SOURCE IS:"+(s1+1)+","+(s2+1));
for(int i2=0;i2<r;i2++)
{
for (int j1 = 0; j1 < c; j1++)
{
{
System.out.print(grid[i2][j1]);
}
}
System.out.println();
}
Queue<Node>q=new LinkedList<Node>();
q.add(new Node(s1,s2));
while(!q.isEmpty())
{
Node p=q.poll();
for(int i=0;i<4;i++)
{
if(((p.x+dx[i]>=0)&&(p.x+dx[i]<r))&&((p.y+dy[i]>=0)&&(p.y+dy[i]<c))&&(grid[p.x+dx[i]][p.y+dy[i]]!='#'))
{//If point is in range
int cx,cy;
cx=p.x+dx[i];
cy=p.y+dy[i];
distances[cx][cy]=distances[p.x][p.y]+1;//Distances
if(grid[cx][cy]=='*')//destination
{
for(Node rm:points)// finding the node and removing it
{
if(rm.x==cx&&rm.y==cy)
{
points.remove(rm);
break;
}
}
grid[cx][cy]='.';//It i walkable again
s1=cx;s2=cy;//next source set
return distances[cx][cy];
}
else if(grid[cx][cy]=='.')//Normal tile. Now setting to visited
{
grid[cx][cy]='V';//Adding to visited
q.add(new Node(cx,cy));
}
}
}
}
return -1;
}
}
这是我的几个测试用例的代码。给出正确答案:
JAVA: http://ideone.com/qoE859
C++ : http://ideone.com/gsCSSL
这是我的代码失败的地方:http://www.codechef.com/status/N1,bholagabbar
你的想法是错误的。我没有读过代码,因为你描述的即使完美实现也会失败。
考虑这样的事情:
x....
.....
..***
....*
*...*
您将像这样穿越迷宫:
x....
.....
..123
....4
*...5
然后从 5
到左下 *
并返回 5
,走 16
步。然而,这:
x....
.....
..234
....5
1...6
走 12
步。
问题的正确解法涉及蛮力。生成*
个位置的所有排列,按照排列给出的顺序访问它们,取最小的。
13!
相当大,所以这可能不够快。在 O(2^k)
中有一个更快的动态规划解决方案,类似于 Travelling Salesman Dynamic Programming Solution (also here).
我现在没有时间谈论解决方案。如果您对此有任何疑问,请随时提出另一个问题,我相信有人会插话(或让这个问题保持开放状态)。