• HDOJ 1175 连连看 DFS


    这题在DFS的同时必须考虑剪枝,,给出三个别人的代码,一个耗时7秒多,一个2秒多,最后一个只有46MS,相差甚大,都是剪枝的功劳。

     1 #include <stdio.h>
     2 #include <string.h>
     3 const int MAX =1002;
     4 bool flag = false;
     5 bool vist[MAX][MAX];
     6 int s,e,map[MAX][MAX];
     7 int dir[5][3]={{1,0},{0,1},{-1,0},{0,-1}};
     8 void DFS(int x,int y,int cnt,int d)
     9 {
    10     if(cnt>2||vist[x][y]||flag)return;
    11     vist[x][y] = true;
    12     for(int i = 0;i < 4;i++)
    13     {
    14         int a,b,t;
    15         a = x + dir[i][0];
    16         b = y + dir[i][1];
    17         if(d!=i) t = cnt +1;
    18         else t = cnt;
    19         if(a==s&&b==e&&t<=2)
    20         {flag = true;return ;}      //printf("x-%d y-%d a-%d b-%d
    ",x,y,a,b);
    21         if(!map[a][b]&&!vist[a][b])
    22           DFS(a,b,t,i);
    23     }
    24     vist[x][y] = false;
    25 }
    26 int main()
    27 {
    28     //freopen("Input.txt","r",stdin);
    29     //freopen("Output.txt","w",stdout);
    30     int n,m,u,v,q;
    31     while(scanf("%d%d",&n,&m),(n||m))
    32     {
    33         memset(map,-1,sizeof(map));
    34         for(int i = 1;i <= n;i++)
    35           for(int j = 1;j <= m;j++)
    36             scanf("%d",&map[i][j]);
    37         scanf("%d",&q);
    38         while(q--)
    39         {
    40             scanf("%d%d%d%d",&u,&v,&s,&e);
    41             flag = false;
    42             memset(vist,false,sizeof(vist));
    43             if(map[u][v]!=map[s][e]||map[u][v]==0);
    44             else
    45               DFS(u,v,-1,-1);
    46             if(flag)
    47               puts("YES");
    48             else
    49               puts("NO");
    50         }
    51     }
    52     return 0;
    53 }
    //【解题思路】:dfs+剪枝。其实没什么好说的,有几个要注意的地方,第一个是判重,第二个是记住最多仅能够进行两次转向。切记,在判断到达目标的时候,需要判断其转向次数是否超过两次,表示个人在此处wa了两次。
    纯暴力版过了之后。有一个剪枝是:在转向两次之后,因为不可转向,所以接下来必须与之前的方式保持一致,这个优化减少了5s左右的时间,原先是7000ms,现在是2000ms。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <cctype>
    #include <map>
    #include <iomanip>
                       
    using namespace std;
                       
    #define eps 1e-8
    #define pi acos(-1.0)
    #define pb push_back
    #define lc(x) (x << 1)
    #define rc(x) (x << 1 | 1)
    #define lowbit(x) (x & (-x))
    #define ll long long
    
    int stx[4]={-1,0,1,0};
    int sty[4]={0,1,0,-1};
    int a[1100][1100];
    int vis[1100][1100];
    int n,m,x,y,xx,yy,q,tmp;
    bool flag;
    
    
    bool solve(int x,int y,int xx,int yy,int cnt,int dir){
        int tx,ty;
        if (x==xx && y==yy && cnt<=2) {return true;}
        if (a[x][y]!=0 && cnt!=-1) return false;
        if (cnt>2) return false;
        else {
            if (cnt==2){   //优化部分
                vis[x][y]=tmp;
                tx=x+stx[dir];
                ty=y+sty[dir];
                if (tx>=0 && tx<n && ty>=0 && ty<m && vis[tx][ty]!=tmp){
                    if (solve(tx,ty,xx,yy,cnt,dir)) return true;
                    }
                vis[x][y]=0;
            }   //end
            else{
            vis[x][y]=tmp;
            for (int i=0; i<4; i++){
                tx=x+stx[i];
                ty=y+sty[i];
                if (tx>=0 && tx<n && ty>=0 && ty<m && vis[tx][ty]!=tmp){
                    if (cnt==-1) {if (solve(tx,ty,xx,yy,cnt+1,i)) return true;}
                    else {if (i!=dir) 
                        {if (solve(tx,ty,xx,yy,cnt+1,i)) return true;}
                            else {if (solve(tx,ty,xx,yy,cnt,dir)) return true;}
                    }                     
                }
            }
            vis[x][y]=0;
            }      
        }
        return false; 
    }
    
    int main() {
        while (~scanf("%d%d",&n,&m)){
            if (n==0 && m==0) break;
            for (int i=0; i<n; i++){
                for (int j=0; j<m; j++)
                   scanf("%d",&a[i][j]);
            }
            memset(vis,0,sizeof(vis));
            scanf("%d",&q);
            for (int i=1; i<=q; i++){
                scanf("%d%d%d%d",&x,&y,&xx,&yy);
                x--;
                y--;
                xx--;
                yy--;
                tmp=i;
                vis[x][y]=tmp;
                if (a[xx][yy]!=a[x][y] || (a[x][y]==a[xx][yy] && a[x][y]==0)) {printf("NO
    "); continue;}
                if (xx==x && yy==y) {printf("NO
    "); continue;}
                flag=false;
                if (solve(x,y,xx,yy,-1,-1)==true) {  
                    printf("YES
    ");
                }
                else printf("NO
    ");
            }
        }
        return 0;
    }
    
    
    
     
    /*
    本题纯属中文,题意很好理解,主要说下需要注意的几点。。
    1。首先需要判断给定的俩个棋子是否相同
    2。如果给定的坐标没有棋子直接输出NO
    3。如果给定的坐标是同一个,也直接输出NO。。不知道测试数据里有没有这么恶心的数据,不过小心为上吧。。
    3。本题搜索需要一点方向感。盲目搜索必定超时,因为本题可以进行俩次转向。。所以可以分为三种情况。我用turn来标记转向的次数
    turn=0 则直接进行下一步搜索。
    turn=1 则需要判断 状态的方向 dir 是否与 需要寻找的棋子位置反向了。。如果反向则放弃搜索、、
    turn=2 则判断是否和目标棋子在一条直线上,而且需要判断方向是否一致。。否则放弃搜索。。
    */
    /*
    46MS 3236K

    */
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    using namespace std;
    int n,m;
    int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    bool used[1005][1005];
    int flag;
    struct State
    {
        int x;
        int y;
        int dir;
        int turn;
        int step;
    };
    State start;
    State end;
    int map[1005][1005];
    bool Judge(State t)
    {
        if(t.x==end.x&&t.y==end.y)
            return 1;
        if(t.turn==0)
            return 1;
        if(t.turn==1)
        {
            if(t.x>end.x&&t.dir==1)
                return 0;
            if(t.y>end.y&&t.dir==3)
                return 0;
            if(t.x<end.x&&t.dir==0)
                return 0;
            if(t.y<end.y&&t.dir==2)
                return 0;
            return 1;
        }
        if(t.turn==2)
        {
            if(t.x==end.x)
            {
                if(t.y>end.y&&t.dir==2)
                    return 1;
                if(t.y<end.y&&t.dir==3)
                    return 1;
            }
            if(t.y==end.y)
            {
                if(t.x>end.x&&t.dir==0)
                    return 1;
                if(t.x<end.x&&t.dir==1)
                    return 1;
            }
            return 0;
        }
        return 1;
    }
    void DFS(State t)
    {
        if(flag)
            return;
        if(t.turn>2)
            return;
        if(t.x==end.x&&t.y==end.y)
        {
            flag=1;
            return;
        }
        int x,y;
        State temp;
        if(t.step==0)
        {
            for(int i=0;i<4;i++)
            {
                temp.x=t.x+move[i][0];
                temp.y=t.y+move[i][1];
                if(temp.x<=0||temp.y<=0||temp.x>n||temp.y>m||used[temp.x][temp.y]==1)
                    continue;
                
                temp.dir=i;
                temp.turn=0;
                temp.step=t.step+1;
                
                if(Judge(temp)==0)
                    continue;
                
                used[temp.x][temp.y]=1;
                DFS(temp);
                used[temp.x][temp.y]=0;
            }
            return;
        }
        if(map[t.x][t.y]!=0)
            return;
        for(int i=0;i<4;i++)
        {
            temp.x=t.x+move[i][0];
            temp.y=t.y+move[i][1];
            if(temp.x<=0||temp.y<=0||temp.x>n||temp.y>m||used[temp.x][temp.y]==1)
                continue;
            if(t.dir!=i)
            {
                temp.dir=i;
                temp.turn=t.turn+1;
            }else
            {
                temp.dir=t.dir;
                temp.turn=t.turn;
            }
            temp.step=1;
            if(Judge(temp)==0)
                continue;
            
            used[temp.x][temp.y]=1;
            DFS(temp);
            used[temp.x][temp.y]=0;
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        #endif
        int t;
        while(scanf("%d %d",&n,&m))
        {
            if(n==0&&m==0)
                return 0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    scanf("%d",&map[i][j]);
            scanf("%d",&t);
            while(t--)
            {
                scanf("%d %d %d %d",&start.x,&start.y,&end.x,&end.y);
                if(start.x==end.x&&start.y==end.y)
                {
                    printf("NO
    ");
                    continue;
                }
                if(map[start.x][start.y]!=map[end.x][end.y]||map[start.x][start.y]==0||map[end.x][end.y]==0)
                {
                    printf("NO
    ");
                    continue;
                }
                memset(used,0,sizeof(used));
                used[start.x][start.y]=1;
                start.turn=0;
                start.step=0;
                flag=0;
                DFS(start);
                if(flag)
                    printf("YES
    ");
                else
                    printf("NO
    ");
            }
        }
        return 0;
    }
    
    
    
     
  • 相关阅读:
    大神的文章
    分布式锁
    分布式事务
    事务两三事
    spring框架笔记
    三个缓存数据库Redis、Memcache、MongoDB
    面向对象面试题
    SSM面试
    单例模式
    Spring Cloud面试题
  • 原文地址:https://www.cnblogs.com/Lee-geeker/p/3234419.html
Copyright © 2020-2023  润新知