点击打开链接
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stack>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1005;
int Arr[maxn][maxn];
bool visit[maxn][maxn];
int x2=0,y2=0,x3=0,y3=0,n=0,m=0,q=0;
int Move[5][2]={{0,0},{0,1},{1,0},{-1,0},{0,-1}};///右下上左,为什么是1,2,3,4
struct Node
{
int x,y,steps,d;//d=1,2,3,4右下上左
};
stack<Node>Q;
void dfs()
{
int i=0;
if(Arr[x2][y2]==0||Arr[x3][y3]==0||Arr[x2][y2]!=Arr[x3][y3]){///是0或者不相等肯定是不可能的额。
printf("NO\n");
return;
}
while(!Q.empty()) Q.pop();
Node now,next;
now.x=x2,now.y=y2,now.steps=0,now.d=0;
Q.push(now);
int ok=0;
while(!Q.empty()){
now=Q.top();Q.pop();///抛出来,bfs一次抛出来是枚举,而dfs一次一次往下。
visit[now.x][now.y]=true;///添加标记已经有过额。
if(now.x==x3&&now.y==y3){
printf("YES\n");
return;
}
for(i=1;i<=4;i++){///四个方向1,2,3,4分别对应右,下,上,左,一次枚举,由于是放栈里的额,所以每次只能取最上面的,同一个对应生的儿子只能用一个不断往下进行,就和递归一样了额。
if(now.d+i==5)continue;///这是什么意思?1+4 2+3这种180度大转弯直接去除额。
next.x=now.x+Move[i][0];
next.y=now.y+Move[i][1];
next.d=i;
if(next.d!=now.d){///转变后的方向
next.steps=now.steps+1;
}
else
next.steps=now.steps;
///以上都是弄好下一个节点的准备工作。
///判断能否进stack的条件
if(next.x>0&&next.x<=n&&next.y>0&&next.y<=m&&((Arr[next.x][next.y]==0&&visit[next.x][next.y]==false&&next.steps<=3)||(next.x==x3&&next.y==y3&&next.steps<=3))){///因为这里wa了很久,第一个是能通过的中间点,第二个是最终结果。为什么小于等于3第一次没有变化,由于初始化d=0,肯定不同多加1
Q.push(next);
}
}
visit[now.x][now.y]=false;///去除标记是必须的!!!!
}
printf("NO\n");
}
int main()
{
int i=0,j=0;
while(scanf("%d%d",&n,&m)){
if(n==0&&m==0)break;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&Arr[i][j]);
}
}
scanf("%d",&q);
while(q--){
scanf("%d%d%d%d",&x2,&y2,&x3,&y3);
memset(visit,false,sizeof(visit));
dfs();
}
}
return 0;
}
///hdu 1175 连连看
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn=1005;
int n,m;
int g[maxn][maxn];
bool vis[maxn][maxn];
int q;
int x2,y2,x3,y3;
int fx[5]={0,0,1,-1,0,};
int fy[5]={0,1,0,0,-1,};
struct p
{
int x;int y;int r;int d;///d=1,2,3,4 右下上左
};
void solve()
{
if(g[x2][y2]==0||g[x3][y3]==0||g[x2][y2]!=g[x3][y3]) { printf("NO\n"); return;}///是0或者不相等肯定是不可能的额。
stack<p> st;
p now,next;
now.x=x2,now.y=y2,now.r=0,now.d=0;
st.push(now);
int ok=0;
while(!st.empty()){
now=st.top();st.pop();///抛出来,bfs一次抛出来是枚举,而dfs一次一次往下。
///vis[now.x][now.y]=true;///标记已经有过额。
///printf("%d %d\n",now.x,now.y);
if(now.x==x3&&now.y==y3) {ok=1;break;}///check
for(int i=1;i<=4;i++){///四个方向1,2,3,4分别对应右,下,上,左,一次枚举,由于是放栈里的额,所以每次只能取最上面的,同一个对应生的儿子只能用一个不断往下进行,就和递归一样了额。
if(now.d+i==5) continue;///这是什么意思?1+4 2+3这种180度大转弯直接去除额。
next.x=now.x+fx[i];///进行移动
next.y=now.y+fy[i];///
next.d=i;///转变后的方向
if(next.d!=now.d)///转变后的方向和转变后的方向不一致
next.r=now.r+1;///变方向次数+1
else next.r=now.r;
///以上都是弄好下一个节点的准备工作。
//cout<<next.x<<' '<<next.y<<' '<<next.d<<' '<<next.r<<endl;
if((g[next.x][next.y]==0&&/*vis[next.x][next.y]==false&&*/next.r<=3)||(next.x==x3&&next.y==y3&&next.r<=3)){///因为这里wa了很久,第一个是能通过的中间点,第二个是最终结果。为什么小于等于3第一次没有变化,由于初始化d=0,肯定不同多加1
st.push(next);//cout<<"in"<<endl;
}
}
///vis[now.x][now.y]=false; //去除标记是必须的,
}
if(ok) printf("YES\n");
else printf("NO\n");
}
int main()
{
//freopen("input.txt","r",stdin);
while(scanf("%d%d",&n,&m)){
if(n==0&&m==0) break;
memset(vis,false,sizeof(vis));
memset(g,INF,sizeof(g));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&g[i][j]);
scanf("%d",&q);
while(q--){
scanf("%d%d%d%d",&x2,&y2,&x3,&y3);
solve();
}
}
return 0;
}