【暴力搜索】[HDU 1175]连连看
这倒题目我看到很多人都用的bfs或者dfs但是其实并不用啊,首先可以发现如果不拐弯,那么A点和B点一定在同一条直线上(这种情况可以不用考虑,等下讲为什么)然后如果存在拐一次的情况那么一定是A和B所在的数轴的交点(也可以不用考虑)但是如果要拐两次呢首先A和B一定形成了一个矩形(假设AB不在同一条数轴上)那么这个拐弯一定平行于这个矩形的一条边(自己想想为什么)然后每一次check枚举一下行和列就好了共线的情况其实就是当他们的矩形枚举到当前的坐标的时候自动就共线了所以没有必要考虑共线的情况同样也不用考虑拐一次的情况。46ms还是比直接宽搜和深搜快些。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1000;
int sum1[MAXN+5][MAXN+5], sum2[MAXN+5][MAXN+5], n, m;
inline int checkposx(int x, int y, int _x){
if(_x > x) return sum2[y][_x] - sum2[y][x];
return sum2[y][x-1] - sum2[y][_x-1];
}
inline int checkposy(int x, int y, int _y){
if(_y > y) return sum1[x][_y] - sum1[x][y];
return sum1[x][y-1] - sum1[x][_y-1];
}
bool check(int x1, int y1, int x2, int y2){
int Maxy = max(y1, y2);
int Maxx = max(x1, x2);
for(int i=1;i<=m;i++){
if(checkposy(x1, y1, i)){
if(i > Maxy) break;
continue;
}
if(checkposy(x2, y2, i)){
if(i > Maxy) break;
continue;
}
if(checkposx(max(x1, x2),i,min(x1, x2)+1)==0){
return true;
}
}
for(int i=1;i<=n;i++){
if(checkposx(x1, y1, i)){
if(i > Maxx) break;
continue;
}
if(checkposx(x2, y2, i)){
if(i > Maxx) break;
continue;
}
if(checkposy(i, max(y1, y2), min(y1, y2)+1)==0){
return true;
}
}
return false;
}
int mabs(int u){return u>0?u:-u;}
int main(){
while(~scanf("%d%d", &n, &m) && n && m){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d", &sum1[i][j]);
sum2[j][i] = sum1[i][j];
sum1[i][j] += sum1[i][j-1];
sum2[j][i] += sum2[j][i-1];
}
int x1, x2, y1, y2;
int q;
scanf("%d", &q);
for(int i=0;i<q;i++){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if(sum1[x1][y1]-sum1[x1][y1-1] == 0 || sum1[x2][y2] - sum1[x2][y2-1] != sum1[x1][y1] - sum1[x1][y1-1]) printf("NO\n");
else if((x1==x2&&mabs(y1-y2) == 1) || (y1==y2 && mabs(x1-x2)==1)) printf("YES\n");
else if(check(x1, y1, x2, y2)) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}