poj 2688 Cleaning Robot BFS+DFS(TSP问题)

题意:

   有一个W*H的房间有一个机器人,一些垃圾(小于等于10)和家具(不能移动或经过),问机器人清理所有的垃圾所用的最小时间,诺有垃圾不能清理输出-1;

想法

      先用BFS求出各点之间的最小步数建图,然后用DFS(由于图的点数小于12所以可用求最短路;(刚开始想只用BFS,从机器人的点找到最近的垃圾点然后再找下一个于此时最近的垃圾点直到找完或不能找,但每次局部的最优不能保证整体的最优,可见求最短路算法

代码实现:

     

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int MAX=106;
const int inf=0xffff;

int Move[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

struct Node
{
    int x,y,step;
};

struct Dirty
{
    int x,y;
}Num[13];

int n,m,Min,k,Flag[13][13];
char Map[MAX][MAX];
bool flag,Used[13];
bool Visted[MAX][MAX];

queue<Node> Q;


int BFS( int x, int y, int x2, int y2 )
{
    while( !Q.empty() )
     Q.pop();
    memset(Visted,0,sizeof(Visted));
    Visted[x][y]=1;
    Node p1;
    p1.x=x;
    p1.y=y;
    p1.step=0;
    Q.push(p1);
    while( !Q.empty() )
    {
        Node Now=Q.front();
        Q.pop();
        for( int i=0; i<4; ++i )
        {
            Node Next;
            Next.x=Now.x+Move[i][0];
            Next.y=Now.y+Move[i][1];
            Next.step=Now.step+1;
            if( Next.x<0 || Next.y<0 || Next.x>=n || Next.y>=m
               || Map[Next.x][Next.y]=='x' )
                continue;
             if( !Visted[Next.x][Next.y] )
             {
                 Visted[Next.x][Next.y]=1;
                 if( Next.x==x2 && Next.y==y2 )
                 {

                     return Next.step;
                 }
                 Q.push(Next);
             }
        }
    }
    return inf;
}

void DFS( int x, int sum, int len )
{
    if( len>Min )
      return;
    if( sum>=k )
    {
        Min=Min<len?Min:len;
        return;
    }
    for( int i=0; i<=k; ++i )
    {
        if( Flag[x][i]!=inf && !Used[i] )
        {
            Used[i]=1;
            DFS(i,sum+1,len+Flag[x][i]);
            Used[i]=0;
        }
    }
}
int main()
{
   //freopen("in.txt","r",stdin);
    while( scanf("%d%d",&m,&n)!=EOF )
    {
        if( !n && !m )
         break;
        k=0;
        getchar();
        for( int i=0; i<n; ++i )
        {
          for( int j=0; j<m; ++j )
          {
             scanf("%c",&Map[i][j]);
             if( Map[i][j]=='o' )
             {
                Num[0].x=i;
                Num[0].y=j;
                Map[i][j]='.';
             }
             else if( Map[i][j]=='*' )
             {
                 Num[++k].x=i;
                 Num[k].y=j;
             }
          }
          getchar();
        }
        Min=0;
        flag=1;
        //cout<<k<<endl<<endl;
        if( k==0 )
        {
            printf("0\n");
            continue;
        }
        for( int i=0; i<=k && flag; ++i )
          for( int j=i+1; j<=k; ++j )
          {
            int temp=BFS(Num[i].x,Num[i].y,Num[j].x,Num[j].y);
            Flag[i][j]=Flag[j][i]=temp;
            if( temp==inf )
            {
                flag=0;
                break;
            }
          }
        if( !flag )
        {
          printf("-1\n");
          continue;
        }
        memset(Used,0,sizeof(Used));
        Min=inf;
        Used[0]=1;
        DFS(0,0,0);
        printf("%d\n",Min);
    }
    return 0;
}


 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值