HDU——1175 连连看
/* 看到这题的限时和空间~,马上不用纠结了,暴搜+剪枝必过 要是哪个大神能告诉我更好的剪枝步骤,我会很感激的。因为 我的代码简直是蜗牛速度~456ms 4900KB水过 */ #include <iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<memory.h> #include<algorithm> using namespace std; #define inf 0x3ffffff #define M 1005 int map[M][M],wan[M][M]; //map是图;wan是弯的数量,主要用来剪枝 int go[4][2]= {{-1,0},{1,0},{0,-1},{0,1}}; //go表示走上、下、左、右方向 int query,s_x,s_y,e_x,e_y,R,C; //query表示问题的个数,s_x,s_y表示第一个棋子的位置, bool F; struct node { int x,y,turn,now; node() {} node(int a,int b,int c,int d) //构造函数万岁~turn代表弯的个数,now表示当前方向 { x=a; y=b; turn=c; now=d; } }; void bfs() { for(int i=1; i<=R; ++i) for(int j=1; j<=C; ++j) wan[i][j]=inf; queue<node> Q; node f(s_x,s_y,-1,6); //f.turn赋值-1,省事~f.now随便一个数都可以只要不是0,1,2,3 Q.push(f); while(!Q.empty()&&!F) { node s=Q.front(); Q.pop(); for(int i=0; i<4; ++i) { int nx=s.x+go[i][0]; int ny=s.y+go[i][1]; int t=s.turn; if(i!=s.now) t++; if(t<=2&&nx==e_x&&ny==e_y) //如果转弯的个数<=2,抵达终点的话,就跳出循环了 { F=true; break; } /*如果nx,ny不在图的范围内,或者遇到不是0的点或者弯>2,或者弯>已记录的弯*/ if(nx<1||nx>R||ny<1||ny>C||map[nx][ny]!=0||t>2||t>wan[nx][ny]) continue; wan[nx][ny]=t; node p(nx,ny,t,i); Q.push(p); //满足以上苛刻条件的点入队 } } } int main() { while(~scanf("%d%d",&R,&C)) { if(R==0&&C==0) break; for(int i=1; i<=R; ++i) for(int j=1; j<=C; ++j) scanf("%d",&map[i][j]); scanf("%d",&query); while(query--) { scanf("%d%d%d%d",&s_x,&s_y,&e_x,&e_y); F=false; /*只有当前的点有棋子并且两棋子是同类型的才需要bfs*/ if(map[s_x][s_y]==map[e_x][e_y]&&map[s_x][s_y]!=0) bfs(); if(F) puts("YES"); else puts("NO"); } } }