我在接受采访时被问到这个问题而我无法解决。
如果你能帮助我解决它,我将非常感激。
问题如下: -
您将获得矩形区域,其左侧和最底层坐标 (0,0)且正确最和最顶层坐标为(x,y)。
在' r' 。
您目前正站在(0,0),想要触及(x,y)而不触及任何圆圈。
你必须告诉它是否可能。
他告诉我你可以自由地在 2点之间移动,没有必要沿着 x或y轴移动。
我想到的解决方案涉及采用 x * y 维度的矩阵,并且对于每个圆圈,标记位于其中的点或触摸它。
之后,从(0,0)开始应用BFS
,检查我们是否可以达到(x,y)。
他告诉我BFS
是错的,我无法弄清楚原因。
我假设圆圈有整数半径并且整数坐标。
他还要求我在没有这些假设的情况下解决问题。
我无法做到。当被问到时,他告诉我这是一个标准问题而且我应该能够在Google上找到它。
我再也不能了。请帮忙!
答案 0 :(得分:3)
面试官错误的是BFS无法使用。每当你进入一个单元格时,检查单元格是否在一个圆圈内,通过检查单元格与你可用的每个其他圆心的距离,如果它在dist< = R内,则无法从该单元格到达目前的特定细胞。我解决了采访中出现的类似问题 - https://www.interviewbit.com/problems/valid-path/ 代码很简单 -
public class Solution {
private class Pair
{
int x ; int y ;
}
ArrayList<Integer> xindex ; ArrayList<Integer> yindex ; int R ;int len ;
public String solve(int x, int y, int n, int r, ArrayList<Integer> xi, ArrayList<Integer> yi) {
int dp[][] = new int[x+1][y+1] ;
len = xi.size() ;
for(int i=0;i<=x;i++)
{
for(int j=0;j<=y;j++)
dp[i][j] = -1 ;
}
xindex = xi ; yindex = yi ;
dp[0][0] = 1 ; R = r*r ;
LinkedList<Pair> q = new LinkedList<Pair>() ;
Pair obj = new Pair() ;
obj.x = 0 ; obj.y = 0 ;
q.add(obj) ;
int arr1[] = {1,1,1,0,-1,-1,-1,0} ;
int arr2[] = {-1,0,1,1,1,0,-1,-1} ;
while(q.size()!=0)
{
Pair temp = q.poll() ;
int x1 = temp.x ;
int x2 = temp.y ;
for(int i=0;i<8;i++)
{
int t1 = x1+arr1[i] ; int t2 = x2+arr2[i] ;
if((t1>=0)&&(t1<=x)&&(t2>=0)&&(t2<=y))
{
if(dp[t1][t2]==-1)
{
boolean res = isValidIndex(t1,t2) ;
if(res==false)
dp[t1][t2] = 2 ;
else
{
dp[t1][t2] = 1 ;
Pair t = new Pair() ;
t.x = t1 ;
t.y = t2 ;
q.add(t) ;
}
}
}
}
if(dp[x][y]!=-1)
break ;
}
if(dp[x][y]==1)
return "YES" ;
return "NO" ;
}
public boolean isValidIndex(int x,int y)
{
for(int i=0;i<len;i++)
{
int x1 = xindex.get(i) ; int x2 = yindex.get(i) ;
if((x==x1)&&(y==x2))
return false ;
int n = (x1-x)*(x1-x) + (x2-y)*(x2-y) ;
if(n<=R)
return false ;
}
return true ;
}
}
答案 1 :(得分:2)
如果两个圆圈正在接触,则在它们的中心之间绘制一条线段。如果圆形接触矩形的边缘,则将其中心与最近侧的投影相连。然后丢弃圈子。这并没有改变障碍物的连接性,你已经将问题转化为平面直线细分中更为家庭化的问题。
一种方法可以是通过分解板中的域,即通过每个中心绘制水平线以在梯形中划分平面。然后通过种子填充方法,可以确定起始板并扩展与其具有共同水平面的板的可达性,直到填充封闭区域或到达出口板。
下面是从左上方的板坯中填充种子的中间步骤。
如果圆心位于规则网格上,则可以进行标准种子填充。
答案 2 :(得分:1)
我认为如果它们的中心之间的距离小于2r,则2个圆圈只能阻挡路径。所以它应该足以构建重叠圆的“岛”,并检查是否有任何岛阻挡从0到(x,y)的路径,即它是否有任何圆与矩形边界相交,使得这些交叉点之间的直线相交点会挡住路径。
答案 3 :(得分:1)
解决此问题的最佳方法是使用dfs搜索。首先让我们考虑一些基本情况,比如是否存在包含两个点中的任何一个(即0,0或x,y)的圆,但不是两个都是,那么答案是&#34; NO&#34;如果存在包含两个点的圆圈,那么我们可以从圆圈列表中删除它。现在我们留下的圆圈不包含这两个点中的任何一个,现在使用这些圆心作为顶点绘制图形,如果它们之间的距离小于或等于2 * R,则连接任意两个顶点还为所有圆保持一个掩模阵列,掩模存储由特定圆切割的边,即如果我们将左垂直边编号为0顶水平边作为1右垂直边作为2而底部水平边作为3然后在掩模中对应于a特定圆圈那些位将是活动的,对应于由该圆圈切割的边。 现在只需执行一个dfs并查看图中是否存在一条路径,该路径显示是否可以使用图形边缘从(0到2或0到3或1到2或1到2)移动(我们用掩码来检查)。如果存在这样的路径,那么回答是&#34;否&#34;否则答案总是&#34;是&#34;。
答案 4 :(得分:1)
我按照安东建议的确切方式做了这个问题。使用DSU制造所谓的岛屿。然后确定以下条件:TB,LR,TR,LB(T:顶部,B:底部,L:左,R:右)交叉点。如果任何一个岛屿形成了这些交叉点,它们肯定会阻挡这条路径,答案就是“不”。 问题可以在采访位找到: https://www.interviewbit.com/problems/valid-path/ 这里给出了相应的解决方案:
#include<bits/stdc++.h>
#include<unordered_set>
using namespace std;
class Solution{
public:
string solve(int A, int B, int C, int D, vector<int> &E, vector<int> &F);
};
#define pii pair<int,int>
int par[1000+5];
int rnk[1000+5];
bool vis[1000+5];
void initialise(){
for(int i=0;i<=1000;i++){
par[i]=i;
rnk[i]=1;
vis[i]=false;
}
}
int findPar(int node){
if(par[node]==node)return node;
return par[node]=findPar(par[node]);
}
void makeUnion(int a,int b){
int parA=findPar(a);
int parB=findPar(b);
if(parA==parB)return;
if(rnk[parA]<rnk[parB])par[parB]=parA;
else if(rnk[parB]<rnk[parA])par[parA]=parB;
else{
rnk[parA]++;
par[parB]=parA;
}
}
bool findBlockage(int root,int X,int Y,int N,int R,vector<pair<int,pii>>vec){
int top=0;
int bottom=INT_MAX;
int left=INT_MAX;
int right=0;
for(int i=0;i<N;i++){
if(par[vec[i].first]==root){
int x=vec[i].second.first;
int y=vec[i].second.second;
top=max(top,y+R);
bottom=min(bottom,y-R);
left=min(left,x-R);
right=max(right,x+R);
}
}
if(top>=Y and bottom<=0)return true;
if(right>=X and left<=0)return true;
if(top>=Y and right>=X)return true;
if(left<=0 and bottom<=0)return true;
return false;
}
string Solution::solve(int X, int Y, int N, int R, vector<int> &E, vector<int> &F) {
vector<pair<int,pii>> vec;
int id=0;
for(int i=0;i<N;i++){
vec.push_back({id,{E[i],F[i]}});
id++;
}
initialise();
for(int i=0;i<N;i++){
for(int j=i;j<N;j++){
if(i==j)continue;
int x1=vec[i].second.first;
int x2=vec[j].second.first;
int y1=vec[i].second.second;
int y2=vec[j].second.second;
if(((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) <= (4*R*R)){
makeUnion(vec[i].first,vec[j].first);
}
}
}
for(int i=0;i<N;i++){
if(!vis[par[vec[i].first]]){
vis[par[vec[i].first]]=1;
bool ret = findBlockage(par[vec[i].first],X,Y,N,R,vec);
if(ret)return "NO";
}
}
return "YES";
}
int main(){
int n,x,y,r;
cin>>x>>y>>n>>r;
vector<int>X(n);
vector<int>Y(n);
for(int i=0;i<n;i++)cin>>X[i];
for(int i=0;i<n;i++)cin>>Y[i];
Solution sol;
cout<<sol.solve(n,x,y,r,X,Y)<<endl;
}
答案 5 :(得分:0)
懒惰 方法:
答案 6 :(得分:0)
使用简单的DP概念针对此问题的递归解决方案(以圆为障碍物,找到从[0,0]
到[x,y]
的路径)
public class Solution {
public long radiusSquare;
public int xDest, yDest;
boolean vis[][];
public final static int[] xDelta = new int[]{0, 1, -1, 0, 1, -1, -1, 1};
public final static int[] yDelta = new int[]{1, 0, 0, -1, 1, -1, 1, -1};
public String solve(int x, int y, int radius, ArrayList<Integer> X, ArrayList<Integer> Y) {
xDest = x; yDest = y;
radiusSquare = radius*radius;
int dp[][] = new int[x+1][y+1]; // = 0 (not visited), = 1 (a valid point), = 2 (invalid)
vis = new boolean[x+1][y+1];
if (recur(0, 0, X, Y, dp)) return "YES";
return "NO";
}
public boolean recur(int xi, int yi, ArrayList<Integer> X,
ArrayList<Integer> Y, int dp[][]){
if (xi == xDest && yi == yDest) return true;
if(vis[xi][yi]) return false; // already processed coordinate
vis[xi][yi] = true;
for (int i =0; i < xDelta.length; i++){
int xArg = xi+xDelta[i];
int yArg = yi+yDelta[i];
if (validCoordinates(xArg, yArg, X, Y, dp) && recur(xArg, yArg, X, Y, dp))
return true;
}
return false;
}
public boolean validCoordinates(int x, int y, ArrayList<Integer> X, ArrayList<Integer> Y, int dp[][]){
if (x < 0 || y < 0 || x > xDest || y > yDest) return false;
if (dp[x][y] != 0){
if (dp[x][y] == 1) return true; // valid coord
if (dp[x][y] == 2) return false;
}
for (int i = 0; i < X.size(); i++){ // loop through each circle.
long sumOfSquare = ((x-X.get(i))*(x-X.get(i))) + ((y-Y.get(i))*(y-Y.get(i)));
if (sumOfSquare <= radiusSquare){
dp[x][y] = 2; // comes on or inside circle
return false;
}
}
dp[x][y] = 1;
return true;
}
}