题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1175
题目大意:= = 因为是中文题,就不多说了。 题目对两块棋子能否消除的限制为 两者之间的连线不能转向2次以上,并且不能穿过其他棋子.
个人想法:dfs.如果能满足题目的条件从一块搜索到另一块,那么就输出YES,否则NO。
= =。 但这边不知道为何,如果没有在转向两次以后进行剪枝(接下去就只朝一个方向走)的话,就是超时.
结合网上的题解,进行了剪枝.
剪了枝之后时间一下子就从超时降到了 3700ms.
- -. 只能在这边感叹搜索算法中剪枝的重要性.
以下是ac代码
#include <stdio.h>
#include <string.h>
int map[1010][1010];
char vis[1010][1010];
int m,n;
int tx[] = {0,0,0,-1,1};
int ty[] = {0,1,-1,0,0};
/* 0:原地,1:上,2:下,3:左,4:右 */
int dfs(int s_x,int s_y,int e_x,int e_y,int dir,int change){
if(change==4)
return 0;
if(s_x == e_x && s_y == e_y){
return 1;
}
if(vis[s_x][s_y])
return 0;
int i;
int ex;
int ey;
int ans = 0;
vis[s_x][s_y] = 1;
if(change==3){
ex = s_x + tx[dir];
ey = s_y + ty[dir];
if(ex>=1 && ex<=m && ey>=1 && ey<=n && (map[ex][ey]==0 || ex==e_x && ey==e_y)){
if(dfs(ex,ey,e_x,e_y,dir,change))
return 1;
}
}/*摘自网上的对于 换了2次后的 优化*/
else{
for(i=1;i<=4;i++){
ex = s_x + tx[i];
ey = s_y + ty[i];
if(ex>=1 && ex<=m && ey>=1 && ey<=n && (map[ex][ey]==0 || ex==e_x && ey==e_y)){
if(dir!=i){
if(dfs(ex,ey,e_x,e_y,i,change+1))
return 1;
}
else{
if(dfs(ex,ey,e_x,e_y,i,change))
return 1;
}
}
}
}
vis[s_x][s_y] = 0;/*为了回溯*/
return 0;
}
int main(int argc, char const *argv[])
{
while(scanf("%d %d",&m,&n)!=EOF&&(m||n)){
int i,j;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&map[i][j]);
int T;
scanf("%d",&T);
int x1,y1,x2,y2;
while(T--){
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
memset(vis,0,sizeof(vis));
if(map[x1][y1]!=map[x2][y2]||(!(map[x1][y1]||map[x2][y2])))
printf("NO\n");
else{
if(dfs(x1,y1,x2,y2,0,0) == 1)
printf("YES\n");
else
printf("NO\n");
}
}
}
return 0;
}
第一篇题解
也是前几道搜索的尝试,第一次体会到剪枝的牛X.
如果有什么问题,欢迎指出,
如果有什么错误,也请看官轻拍.