zoukankan      html  css  js  c++  java
  • HDU 1813 Escape from Tetris (IDA*)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1813

    题意:给你一个n*n的迷宫,其中0代表有一个人在这个位置,1代表墙,现在要求一个路线,使所有的人通过这个路线都可以走到迷宫的边界

    注意当到达边界就相当于出去了不用继续走了,一个格子可以容纳很多人。

    题解:先用BFS求出迷宫内部的点走到边界的最小步数(为了后面的IDA*剪枝),因为有很多状态,不好表示,所以可以想到用IDA*算法,在dfs的时候每次内部的点安同一个方向走,当某个点走到边界或遇见墙时不变,其他的点还是继续走。

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <list>
    #include <deque>
    #include <queue>
    #include <iterator>
    #include <stack>
    #include <map>
    #include <set>
    #include <algorithm>
    #include <cctype>
    using namespace std;
    
    #define si1(a) scanf("%d",&a)
    #define si2(a,b) scanf("%d%d",&a,&b)
    #define sd1(a) scanf("%lf",&a)
    #define sd2(a,b) scanf("%lf%lf",&a,&b)
    #define ss1(s)  scanf("%s",s)
    #define pi1(a)    printf("%d
    ",a)
    #define pi2(a,b)  printf("%d %d
    ",a,b)
    #define mset(a,b)   memset(a,b,sizeof(a))
    #define forb(i,a,b)   for(int i=a;i<b;i++)
    #define ford(i,a,b)   for(int i=a;i<=b;i++)
    
    typedef long long LL;
    const int N=11;
    const int INF=0x3f3f3f3f;
    const double PI=acos(-1.0);
    const double eps=1e-7;
    
    int n,depth;
    int cnt;//表示不是边界点的个数
    int x[101],y[101];//存放不是边界的点
    int xh[N][N];//xh[i][j]表示ij到边界的最短距离,由BFS生成
    char str[N][N];
    int ans[1000];//存放方向
    int dir[4][2]={0,1,-1,0,1,0,0,-1};//east north south west 按照字典序
    bool flag;
    
    struct node
    {
        int x,y;
    }w,e;
    
    bool bianjie(int x,int y)
    {
        if(x==0||x==n-1||y==0||y==n-1)
            return true;
        return false;
    }
    
    bool inmap(int x,int y)
    {
        if(x>=0&&x<n&&y>=0&&y<n)
            return true;
        return false;
    }
    
    void bfs()
    {
        queue<node> q;
        q.push(w);
        xh[w.x][w.y]=0;
        while(!q.empty())
        {
            e=q.front();
            q.pop();
    
            for(int i=0;i<4;i++)
            {
                w.x=e.x+dir[i][0];
                w.y=e.y+dir[i][1];
                if(inmap(w.x,w.y)&&str[w.x][w.y]=='0')
                {
                    if(xh[w.x][w.y]<=xh[e.x][e.y]) continue;
                    xh[w.x][w.y]=xh[e.x][e.y]+1;
                    q.push(w);
                }
            }
        }
    }
    
    int geth(int x[],int y[])//统计最大的距离
    {
        int ss=0;
        forb(i,0,cnt)   ss=max(ss,xh[x[i]][y[i]]);
        return ss;
    }
    
    void dfs(int tx[],int ty[],int de)
    {
        if(flag)    return ;
        if(geth(tx,ty)>de)  return ;
        if(de==0)//或者geth(tx,ty)==0
        {
            flag=true;
            return ;
        }
        for(int i=0;i<4;i++)
        {
            int xx[101],yy[101];
            for(int j=0;j<cnt;j++)//不是边界的点都按照i这个方向走
            {
                xx[j]=tx[j];    yy[j]=ty[j];
                if(bianjie(xx[j],yy[j]))    continue;
                if(str[xx[j]+dir[i][0]][yy[j]+dir[i][1]]=='0')
                {
                    xx[j]+=dir[i][0];
                    yy[j]+=dir[i][1];
                }
            }
            ans[de]=i;
            dfs(xx,yy,de-1);
            if(flag)    return;//这个地方一定要加上这一句,不然会被覆盖
        }
    }
    
    void IDA()
    {
        flag=false;
        depth=geth(x,y);
        while(1)
        {
            dfs(x,y,depth);
            if(flag)
            {
                for(int i=depth;i>0;i--)
                {
                    if(ans[i]==0)   puts("east");
                    if(ans[i]==1)   puts("north");
                    if(ans[i]==2)   puts("south");
                    if(ans[i]==3)   puts("west");
                }
                break;
            }
            depth++;
        }
    }
    
    int main()
    {
    //    freopen("input.txt","r",stdin);
        int ca=0;
        while(~si1(n))
        {
            forb(i,0,n) ss1(str[i]);
            mset(xh,INF);//初始化为无穷大
            cnt=0;
            forb(i,0,n)
                forb(j,0,n)
                    if(str[i][j]=='0')
                    {
                        w.x=i;  w.y=j;
                        if(!bianjie(i,j))
                        {
                            x[cnt]=i;
                            y[cnt]=j;
                            cnt++;
                        }
                        else
                            bfs();//求出每个点要走出去的最小步数
                    }
            if(ca++)    printf("
    ");
            if(cnt==0||geth(x,y)==INF)  {continue;}//都是边界点|走不出去的情况
    
            IDA();
        }
        return 0 ;
    }
    


     

  • 相关阅读:
    新版ubuntu中打开终端的方法和安装ssh 的方法
    HTML中利用404将老域名重定向到新域名
    KeelKit 1.0.3500.25185
    如何制作VSPackage的安装程序
    一副漫画:IE6滚回你老家去
    “表单控件”与“实体类”
    VS2005中得到 Web页面 或 窗体的 IDesignerHost
    一句SQL搞定分页
    CodeDom Assistant CodeDom的强大工具, 有些BUG修正了下,发到CodePlex,大家有需要的可以看看
    VS2005 出现 The OutputPath property is not set for this project. 错误的解决方法
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3341569.html
Copyright © 2011-2022 走看看