hdu 1175 dfs

背景:数次超时,数次wa,dfs还是存在代码不规范的情况,什么时候回溯没有考虑清楚。后来看了模板化的搜索写法,发现我一直没有用过visit[M][M]标记访问过的点,而是直接在原图上标记,这样是节约内存但是,容易出错!

思路:这个转向题最大的特点是,创建了一个结构体,即有转向数count,也有上次走来的方向up,一旦up和这次的方向数不一样,count就加一(我的代码少考虑了,起点和终点在同一点的情况,但数据没有这种,所以侥幸过了,要是有这样的数据,得找好久才能找出错点,起点和终点是同一点的情况,以后写搜索都得注意了)。

关于bfs的解法:这个题开始也可以想到bfs解法,但是有一点就是bfs不能保证从一点到下一点是转向最少的点啊,网上有人通过改变转向的次序,而夺过数据水过。后来看到正确写法是用三维标记数组:visit[1009][1009][4] 要保证每一个位置的四个方向都遍历了。

//hdu 1175
#include <iostream>
#include<cstdio>
#include<cstring>
#define M 1009
using namespace std;
int diagram[M][M],n,m,query,dir[4][2]={1,0,-1,0,0,-1,0,1},ans;
struct place{int x,y,up,count;}s,temp1,temp2,e;
void dfs(place temp1);

void scan(void){
     for(int i=1;i <= n;i++){
        for(int j=1;j <= m;j++){
            scanf("%d",&diagram[i][j]);
        }
     }
     scanf("%d",&query);
}

int main(void){
    while(scanf("%d%d",&n,&m),n*n+m*m){
        scan();
        while(query--){
            ans=M;
            scanf("%d%d%d%d",&s.x,&s.y,&e.x,&e.y);
            s.count=0;
            s.up=-1;
            if(diagram[s.x][s.y] != diagram[e.x][e.y] || !diagram[s.x][s.y]) ans=M;    //终点棋子和起点棋子不一样,或一样都为0,直接输出no
            else dfs(s);
            if(ans <= 2) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

void dfs(place temp1){
     if(temp1.x == e.x && temp1.y == e.y){     //判断是否达到终点。
        if(temp1.count < ans) ans=temp1.count;
        return;
     }
     int key=diagram[temp1.x][temp1.y];    //回溯记录
     if(!key) diagram[temp1.x][temp1.y]=-M;
     for(int i=0;i < 4;i++){
         temp2.x=temp1.x+dir[i][0];
         temp2.y=temp1.y+dir[i][1];
         temp2.up=i;
         if(i != temp1.up && temp1.up != -1) temp2.count=temp1.count+1;
         else temp2.count=temp1.count;    //判断是否转向
         if(temp2.count > 2 || temp2.x < 1 || temp2.x > n || temp2.y < 1 || temp2.y > m) continue;
         if(temp2.count == 2 && (temp2.x != e.x && temp2.y != e.y)) continue;    //对于已经转了两次弯的,不能再转弯了,剪枝。
         if(diagram[temp2.x][temp2.y] == 0 || (temp2.x == e.x && temp2.y == e.y)){
             dfs(temp2);
             if(ans <= 2){diagram[temp1.x][temp1.y]=key;return;}    //核心剪枝:一旦找到满足条件的路径就跳出所有循环,跳出循环之前,必须要回溯。
         }
     }
     diagram[temp1.x][temp1.y]=key;    //回溯
     return;
}
时间: 2024-08-22 06:31:07

hdu 1175 dfs的相关文章

HDU - 1175 连连看 DFS (记录方向)

连连看HDU - 1175 "连连看"相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去.不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的.现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过. 玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能

【dfs】hdu 1175 连连看

[dfs]hdu 1175 连连看 题目链接:hdu 1175 连连看 题目大意 连连看,问能否成功? 题意很简单,就是我们平时玩的连连看的游戏规则,貌似dfs和bfs都能做,笔者就做了个dfs(好想),超时了好几次,原因是dfs(int d)与终点的d重载矛盾了,所以还是要小心. 说一下思路 神器的剪枝:if(t==2&&x!=c&&y!=d) return;这一部剪枝妙笔回春,9000+MS优化到100+MS啊:如果转了2次,但是目标与当前位置不在同一行或同一列就不满足

hdu 1175 连连看 (深搜)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 题目大意:如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子)这样的两个棋子可以消掉.还有一个要注意的地方的就是转弯.转弯的次数不超过两次,这两个棋子才可以在棋盘上消去~ 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int

hdu 1175 bfs 转弯题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 和之前的1728类似.就是判断转弯数,建立一个用于记录转弯数的数组.. 还有就是对于特殊情况要进行考虑,比如起点与终点相同的情况,对于本题来说是不可以消去的应该输出NO.还有就是起点或终点是零这也是不行的,因为0代表没有棋子... 还有在判断能不能走的时候要小心,对于判断条件一定要小心,不要图赶快写.. 错误的地方都写在注释中了.. 代码: // hdu 1175 bfs 转弯数 //1.起点

hdu 1175 连连看(模拟循环队列)

连连看 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 18149    Accepted Submission(s): 4741 Problem Description "连连看"相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以通过一条线连起来(这条

hdu 4109 dfs+剪枝优化

求最久时间即在无环有向图里求最远路径 dfs+剪枝优化 从0节点(自己增加的)出发,0到1~n个节点之间的距离为1,mt[i]表示从0点到第i个节点目前所得的最长路径 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const

HDU 1015 dfs回溯

题目真长.....看了好长时间才看懂.. 就是给你一个32位数字和一个最多15个字符的字符串,从字符串中选出5个字符,若满足题中给的那个式子,输出字典序最大的那5个字符,若不满足,输出no solution. 为了解决字典序问题,在输入字符串后,把字符串按从大到小排一下序,搜索一下若满足条件输出即可. 贴代码. 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <

hdu 1312 DFS算法简单题

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 此题与油田那题很像是练习深搜的好题,题意是从"@"开始,遍历整个图,找到连接的 "."有多少个 但要考虑变化,简单处理下就行了,主要是斜角的不要了,而且判断结束方式也不一样 具体看代码吧 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

HDU 5143 DFS

分别给出1,2,3,4   a, b, c,d个 问能否组成数个长度不小于3的等差数列. 首先数量存在大于3的可以直接拿掉,那么可以先判是否都是0或大于3的 然后直接DFS就行了,但是还是要注意先判合法能否进入下层递归来减少内存消耗. /** @Date : 2017-09-27 15:08:23 * @FileName: HDU 5143 DFS.cpp * @Platform: Windows * @Author : Lweleth ([email protected]) * @Link :