UVa OJ 10047

1、这道题乍一看让人摸不着头脑,因为和普通的bfs不同,如果颜色不达到要求,即使到了终点也不能结束程序。这就意味着已访问过的结点还可以访问。这要怎么办呢?我没有想出来,上网查后才知道vis最初的定义原来是标记“状态”,而不是“格子”,所以我们有必要用一个四维的vis数组来记录某状态是否访问过,状态包括横坐标、纵坐标、方向、颜色。

2、刚开始我是枚举四个方向,不知为何总是WA,调试了很久也没有结果,后来看了别人的程序才知道应该枚举三个状态,即:向左转、直走、向右转。这样的操作更为基本,不容易出错。

3、最后还要注意的一个地方就是“更新最短时间”语句的位置,只有直走才需要更新(因为只有移动才有可能到达终点),而且更新应该放在if语句里面,而不是外面。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int m,n,bx,by,ex,ey;
char a[30][30];
int vis[30][30][4][5];
int q[40000];
int q_dir[4000];
int q_color[40000];
int time[40000];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int bfs(int x,int y){
    int front=0,rear=0,d,u,mind=2147483647,di,co,nx,ny;
    u=x*n+y;
    vis[x][y][0][0]=1;time[front]=0;q_dir[front]=0;q_color[front]=0;
    q[rear++]=u;
    while(front<rear){
       u=q[front++];
       x=u/n;y=u%n;
       nx=x+dx[q_dir[front-1]];ny=y+dy[q_dir[front-1]];
       di=q_dir[front-1];co=(q_color[front-1]+1)%5;
       if(nx>=0&&nx<m&&ny>=0&&ny<n&&a[nx][ny]!='#'&&!vis[nx][ny][di][co]){
             int v=nx*n+ny;
             q[rear++]=v;
             vis[nx][ny][di][co]=1;
             q_dir[rear-1]=di;
             q_color[rear-1]=co;
             time[rear-1]=time[front-1]+1;
             if(nx==ex&&ny==ey&&q_color[rear-1]==0)
                mind=min(mind,time[rear-1]);
       }
       nx=x;ny=y;
       di=(q_dir[front-1]-1+4)%4;co=q_color[front-1];
       if(a[nx][ny]!='#'&&!vis[nx][ny][di][co]){
             int v=nx*n+ny;
             q[rear++]=v;
             vis[nx][ny][di][co]=1;
             q_dir[rear-1]=di;
             q_color[rear-1]=co;
             time[rear-1]=time[front-1]+1;
       }
       nx=x;ny=y;
       di=(q_dir[front-1]+1)%4;co=q_color[front-1];
       if(a[nx][ny]!='#'&&!vis[nx][ny][di][co]){
             int v=nx*n+ny;
             q[rear++]=v;
             vis[nx][ny][di][co]=1;
             q_dir[rear-1]=di;
             q_color[rear-1]=co;
             time[rear-1]=time[front-1]+1;
       }
    }
    if(mind!=2147483647) return mind;
    else return -1;
}
int main()
{
   //freopen("a.txt","r",stdin);
   bool flag=false;
   int ans,count=0;
   while(scanf("%d%d",&m,&n)==2){
        if(!m&&!n) break;
        getchar();
        memset(vis,0,sizeof(vis));
        for(int i=0;i<m;i++){
          for(int j=0;j<n;j++){
             scanf("%c",&a[i][j]);
             if(a[i][j]=='S'){bx=i;by=j;}
             if(a[i][j]=='T'){ex=i;ey=j;}
          }
          getchar();
        }
        if(flag)
          printf("\n");
        printf("Case #%d\n",++count);
        ans=bfs(bx,by);
        if(ans==-1)
          printf("destination not reachable\n");
        else
          printf("minimum time = %d sec\n",ans);
        flag=true;
    }
    //system("PAUSE");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值