【算法实验三】--【分支限界法】--独轮车

1044.独轮车

时限:1000ms 内存限制:10000K  总时限:3000ms

描述

独轮车的轮子上有红、黄、蓝、白、绿(依顺时针序)5种颜色,在一个如下图所示的20*20的迷宫内每走一个格子,轮子上的颜色变化一次。独轮车只能向前推或在原地转向。每走一格或原地转向90度均消耗一个单位时间。现给定一个起点(S)和一个终点(T),求独轮车以轮子上的指定颜色到达终点所需的最短时间。

 

输入

本题包含一个测例。测例中分别用一个大写字母表示方向和轮子的颜色,其对应关系为:E-东、S-南、W-西、N-北;R-红、Y-黄、B-蓝、W-白、G-绿。在测试数据的第一行有以空格分隔的两个整数和两个大写字母,分别表示起点的坐标S(x,y)、轮子的颜色和开始的方向,第二行有以空格分隔的两个整数和一个大写字母,表示终点的坐标T(x,y)和到达终点时轮子的颜色,从第三行开始的20行每行内包含20个字符,表示迷宫的状态。其中'X'表示建筑物,'.'表示路.

 

输出

在单独的一行内输出一个整数,即满足题目要求的最短时间。

 

输入样例

3 4 R N
15 17 Y
XXXXXXXXXXXXXXXXXXXX
X.X...XXXXXX......XX
X.X.X.....X..XXXX..X
X.XXXXXXX.XXXXXXXX.X
X.X.XX....X........X
X...XXXXX.X.XX.X.XXX
X.X.XX....X.X..X.X.X
X.X.X..XX...XXXX.XXX
X.X.XX.XX.X....X.X.X
X.X....XX.X.XX.X.X.X
X.X.X.XXXXX.XX.X.XXX
X.X.X.XXXXX....X...X
X.X.......X.XX...X.X
X.XXX.XXX.X.XXXXXXXX
X.....XX.......X...X
XXXXX....X.XXXXXXX.X
X..XXXXXXX.XXX.XXX.X
X.XX...........X...X
X..X.XXXX.XXXX...XXX
XXXXXXXXXXXXXXXXXXXX

 

输出样例

56

解析:这个题也是一个比较典型的分支限界法的题,即用广搜法。分支限界法和回溯法解题的区别是:回溯法是求这个题是否有解,而分支限界法是在已知这个题有解的情况下,求最优解。这也是深搜和广搜的根本区别。这也决定了深搜可以直接套用回溯法的模板,广搜必须用队列实现。代码如下:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stdio.h>
using namespace std;
char map[21][21];
int used[21][21][5][4]={0};
int step[21][21][5][4]={0};
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int sx,sy,sc,sd;
int tx,ty,tc;
typedef struct node
{
    int row;
    int col;
    int colour;
    int dire;
}Piont;
queue<Piont>q;
Piont find(Piont x,int i)
{
    if(i==0)
    {
        x.colour=(x.colour+1)%5;
        x.row=x.row+dx[x.dire];
        x.col=x.col+dy[x.dire];
    }
    if(i==1)
    {
        x.dire=(x.dire+1)%4;//向东转
    }
    if(i==2)
    {
        x.dire=(x.dire+3)%4;//向西转
    }
    return x;
}
int bfs(int x,int y,int c,int d)
{
    int i;
    Piont u,v;
    u.row=x,u.col=y,u.colour=c,u.dire=d;//吧当前的位置状况存给u
    q.push(u);//把当前的这个位置入栈
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        for(i=0;i<3;i++)
        {//当到达一个位置后,有三种选择:直走,向左转和向右转。往前走的话,变颜色坐标,后两个只变方向
            v=find(u,i);

            if(v.row==tx&&v.col==ty&&v.colour==tc)
                return step[u.row][u.col][u.colour][u.dire]+1;
            if(v.row>=0&&v.row<21&&v.col>=0&&v.col<21&&used[v.row][v.col][v.colour][v.dire]==0&&map[v.row][v.col]=='.')
            {
                q.push(v);
                used[v.row][v.col][v.colour][v.dire]=1;
                step[v.row][v.col][v.colour][v.dire]=step[u.row][u.col][u.colour][u.dire]+1;

            }
        }
    }
    return -1;
}
int changercolour(char x)
{//红黄蓝白绿01234
    if(x=='R')
    return 0;
    if(x=='Y')
    return 1;
    if(x=='B')
    return 2;
    if(x=='W')
    return 3;
    if(x=='G')
    return 4;
}
int changerdire(char x)
{//东南西北0123
    if(x=='E')
    return 0;
    if(x=='S')
    return 1;
    if(x=='W')
    return 2;
    if(x=='N')
    return 3;
}
int main()
{
    int i,j,num;
    char scolour,sdire,tcolour;
    cin>>sx>>sy>>scolour>>sdire;//初始坐标颜色方向
    cin>>tx>>ty>>tcolour;
    for(i=1;i<21;i++)
    {
        for(j=1;j<21;j++)
            cin>>map[i][j];
    }
    sc=changercolour(scolour);
    sd=changerdire(sdire);
    tc=changercolour(tcolour);
    used[sx][sy][sc][sd]=1;
    num=bfs(sx,sy,sc,sd);
    cout<<num<<endl;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值