hdu 1175
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1175
题意:中文不多说。
mark:3WA,各种脑残错误不多说。最后一个竟然是忘记写return 0。无法直视。
说下算法,这题感觉既可以dfs,也可以bfs,但是都不是特好写。好在转弯数限定为2次。那么可以尝试一下比较生猛的写法:先把起点和终点不需转弯直接可达的区域染色(形状大概是2个十字架)。如果这2个区域有重合的地方,自然是YES了。如果没有,扫每一行和每一列,看是否存在2个不同颜色区域之间都没有别的棋子(全0)的情况,如果有,则YES。否则NO。
代码:
1 # include <stdio.h> 2 # include <string.h> 3 4 5 int n, m ; 6 int sx, sy, dx, dy ; 7 int g[1010][1010], vis[1010][1010] ; 8 int tab[4][2] = {0,-1,0,1,1,0,-1,0} ; 9 10 11 void set(int x, int y, int flag) 12 { 13 int xx, yy ; 14 vis[x][y] += flag ; 15 int i ; 16 for (i = 0 ; i < 4 ; i++) 17 { 18 for (xx = x+tab[i][0], yy = y+tab[i][1] ; xx>0 && xx <= n && yy>0&&yy <= m ; xx+=tab[i][0], yy +=tab[i][1]) 19 { 20 if (g[xx][yy] != 0) break ; 21 vis[xx][yy] += flag ; 22 } 23 } 24 } 25 26 27 int gao() 28 { 29 int i, j, flag ; 30 if (g[sx][sy] != g[dx][dy]) return 0 ; 31 if (g[sx][sy]==0) return 0 ; 32 memset (vis, 0, sizeof(vis)) ; 33 set(sx, sy, 1) ; 34 set(dx, dy, 2) ; 35 for(i = 1 ; i <= n ; i++) 36 for (j = 1 ; j <= m ; j++) if (vis[i][j] >= 3) return 1 ; 37 38 for (i = 1 ; i <= n ; i++) 39 for (flag = 0, j = 1 ; j <= m ; j++) 40 { 41 if (flag == 0 && vis[i][j] != 0) flag = vis[i][j] ; 42 else if (flag != 0 && flag != vis[i][j] && vis[i][j]!=0) return 1; 43 else if (flag != 0 && g[i][j] != 0) flag = 0 ; 44 } 45 46 for (j = 1 ; j<=m ; j++) 47 for (flag = 0, i = 1 ; i <= n ; i++) 48 { 49 if (flag == 0 && vis[i][j] != 0) flag = vis[i][j] ; 50 else if (flag != 0 && flag != vis[i][j] && vis[i][j]!=0) return 1; 51 else if (flag != 0 && g[i][j] != 0) flag = 0 ; 52 } 53 return 0 ; 54 } 55 56 57 int main () 58 { 59 int i, j, q ; 60 while (~scanf ("%d%d", &n,&m) && (n||m)) 61 { 62 for (i = 1 ; i <= n ; i++) 63 for (j = 1 ; j <= m ; j++) 64 scanf ("%d", &g[i][j]) ; 65 scanf ("%d", &q) ; 66 while (q--) 67 { 68 scanf ("%d%d%d%d", &sx, &sy, &dx, &dy) ; 69 puts (gao()?"YES":"NO") ; 70 } 71 } 72 return 0 ; 73 }