zoukankan      html  css  js  c++  java
  • Japan 2005 Domestic Cleaning Robot /// BFS 状压 二进制位运算 结构体内构造函数 oj22912

    题目大意:

    输入w h,接下来输入h行w列的图

    ':干净的点;  ' * ' :垃圾;  ' ' : 墙;  ' ' : 初始位置;

    输出 清理掉所有垃圾的最短路径长度 无则输出-1

    Sample Input

    7 5
    .......
    .o...*.
    .......
    .*...*.
    .......
    15 13
    .......x.......
    ...o...x....*..
    .......x.......
    .......x.......
    .......x.......
    ...............
    xxxxx.....xxxxx
    ...............
    .......x.......
    .......x.......
    .......x.......
    ..*....x....*..
    .......x.......
    10 10
    ..........
    ..o.......
    ..........
    ..........
    ..........
    .....xxxxx
    .....x....
    .....x.*..
    .....x....
    .....x....
    0 0

    Sample Output

    8
    49
    -1

    题解

    用bfs求出任意两点间的距离然后转换成tsp问题,用dfs解

    /*
    题意:给一个 n*m的图,有一个机器人从一点开始清理垃圾,要求把所有的垃圾清理完,求最短的路径
    
    思路:这个题可以先用bfs求出任意两点间的距离然后转换成tsp问题,用dfs解。
    
    这个题还可以用状态压缩bfs写,但写了一次没过,再试试。
    */
    
    #include <cstdlib>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    
    #define INF 0x7fffffff
    #define N 22
    
    using namespace std;
    
    struct node
    {
        int x,y,step;
    }p[N*N],s,e;
    
    char map[N][N];
    int n,m,d[4][2]={0,1,1,0,0,-1,-1,0},used[N][N];
    int dis[N][N],ans,use[N],cnt;
    
    bool ok(int x,int y)
    {
        return x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='x'&&!used[x][y];
    }
    
    int bfs()
    {
        memset(used,0,sizeof(used));
        int i;
        queue<node> q;
        q.push(s);
        while(!q.empty())
        {
            node cur=q.front(),next;
            q.pop();
            for(i=0;i<4;i++)
            {
                next.x=cur.x+d[i][0];
                next.y=cur.y+d[i][1];
                next.step=cur.step+1;
                if(ok(next.x,next.y))
                {
                    used[next.x][next.y]=1;
                    if(next.x==e.x&&next.y==e.y)
                        return next.step;
                    q.push(next);
                }
            }
        }
        return INF;
    }
    
    void dfs(int s,int num,int length)
    {
        int j;
        if(num==0&&ans>length)
        {
            ans=length;
            return ;
        }
        if(length>ans)
            return ;
        for(j=0;j<cnt;j++)
        {
            if(dis[s][j]!=INF&&!use[j])
            {
                use[j]=1;
                length+=dis[s][j];
                dfs(j,num-1,length);
                num+1;
                length-=dis[s][j];
                use[j]=0;
            }
        }
    }
    
    int main()
    {
        int i, j, start, flag;
        while(scanf("%d%d",&m,&n)&&(n||m))
        {
            cnt=flag=0;
            for(i=0;i<n;i++)
            {
                scanf("%s",map[i]);
                for(j=0;j<m;j++)
                {
                    if(map[i][j]=='o'||map[i][j]=='*')
                    {
                        p[cnt].x=i,p[cnt].y=j;
                        if(map[i][j]=='o')
                            start=cnt;
                        cnt++;
                        
                    }
                    dis[i][j]=INF;
                }
            }
            
            //memset(dis,INF,sizeof(dis));
            for(i=0;i<cnt;i++)
                for(j=i+1;j<cnt;j++)
                {
                    s=p[i],e=p[j],s.step=0;
                    dis[i][j]=dis[j][i]=bfs();
                    if(dis[i][j]==INF)
                    {
                        flag=1;
                        break;
                    }
                }
    /*       for(i=0;i<cnt;i++)
            {
                for(j=0;j<cnt;j++)
                    printf("%d	",dis[i][j]);
                puts("");
            }*/ 
            if(flag)
                puts("-1");
            else
            {
                ans=INF;
                memset(use,0,sizeof(use));
                use[start]=1;
                dfs(start,cnt-1,0);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    View Code

    状压 BFS 

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    struct NODE
    {
        int ni,nj,mask,len;
        NODE(){};
        NODE(int n_i,int n_j,int nmask,int nlen):
            ni(n_i),nj(n_j),mask(nmask),len(nlen){};
    };
    char G[35][35];
    int w,h,cnt,st_i,st_j;
    int vis[35][35][1<<11],flag[35][35];
    int mi[]={0,0,1,-1},mj[]={1,-1,0,0};
    
    bool bound(int i,int j) /// 判断是否越界
    {
        return (i>h||i<1||j>w||j<1);
    }
    bool OK(int mask) /// 判断垃圾是否被清理
    {
        for(int i=0;i<cnt;i++)
            if(mask & (1<<i)); /// 用mask二进制的各个位表示各个垃圾
            else return 0;
        return 1;
    }
    int BFS()
    {
        memset(vis,0,sizeof(vis));
        int ans=INF;
        queue<NODE> q;
        q.push(NODE(st_i,st_j,0,0)); /// 构造函数的便利之处
    
        while(!q.empty())
        {
            NODE tmp=q.front(); q.pop();
    
            if(OK(tmp.mask)) /// 返回1表明垃圾清理光了 就更新ans值
            {
                ans=min(ans,tmp.len);
                continue;
            }
    
            if(vis[tmp.ni][tmp.nj][tmp.mask]) continue; 
            /// 该点的mask状态已出现过 则忽略该点
            else vis[tmp.ni][tmp.nj][tmp.mask]=1;
            /// 未出现过 则标记为已出现过 
    
            for(int i=0;i<4;i++)
            {
                int newi=tmp.ni+mi[i],newj=tmp.nj+mj[i],newmask=tmp.mask;
    
                if(bound(newi,newj)||G[newi][newj]=='x') continue;
                 ///  若越界或该点为墙 则忽略该点
    
                if(G[newi][newj]=='*')
                    newmask=tmp.mask | (1<<flag[newi][newj]);
                 /*  假如目前是三号垃圾 更新状态
                    即若此时tmp.mask的二进制为011(第一二号垃圾已清除)
                    newmask=011 | 1<<3=111(第一二三号垃圾已清除)
                    很明显 将垃圾状态压缩 用mask的二进制表示 */
    
                if(vis[newi][newj][newmask]) continue;
                 ///  若该新点的该状态已出现过 则忽略该点 若无则放入队列
                q.push(NODE(newi,newj,newmask,tmp.len+1));
            }
        }
        return ans==INF ? -1:ans; 
    }
    
    int main()
    {
        while(~scanf("%d%d",&w,&h)&&(w||h))
        {
            cnt=0;
            for(int i=1;i<=h;i++)
                for(int j=1;j<=w;j++)
                {
                    scanf(" %c",&G[i][j]);
                    if(G[i][j]=='o')  st_i=i,st_j=j; /// 记下所在位置
                    else if(G[i][j]=='*') flag[i][j]=cnt++; 
                 /// 记下垃圾的位置 并为其编号 防止重复清扫
                }
            if(!cnt) printf("0
    ");
            else printf("%d
    ",BFS());
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    [转]在自己的项目中调用别人的库的方法(static lib库,dynamic lib库以及dll动态库)
    前端、后台、客户端以及服务器
    C# 使用j
    C# Linq技术中SelectMany() 获取list对象的属性 汇总成为一个新的集合
    C# 集合的扩展方法-查询表达式GroupBy()的使用 转
    C# ASP.NET MVC中Filter过滤器的使用 通过注册到Global.asax注册为全局 过滤所有action
    C# ASP.NET MVC中有四种Filter 过滤器类型 通过标签 Attribute加到action上面
    C# 《Asp.Net Web Api 》-----路由机制 转
    C# ASP.NET MVC5路由系统机制详细讲解(转)
    MVC 自定义数据校验规则 Validation
  • 原文地址:https://www.cnblogs.com/zquzjx/p/8584613.html
Copyright © 2011-2022 走看看