独轮车(广搜_队列)

时限: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<stdio.h>
struct colornode
{
    int row;//该状态的行
    int col;//该状态的列
    int color;//该状态的颜色(五种颜色,0-R,1-Y,2-B,3-W,4-G)
    int direction;//该状态的方向(四个方向,0-W,1-S,2-E,3-N,西南东北)
    int num;//该状态的最小步数
};
struct colornode s,t;//起点,终点
struct colornode open[2000];//队列
int head,tail,openlen=2000;
int direct[4][2]={{0,-1},{1,0},{0,1},{-1,0}};//向左,下,右,上四个方向转时,行列的增加值
int a[20][20]={0},n=20;//a数组表示迷宫,n为迷宫边长
int b[20][20][5][4] = {0};//b数组表示搜索时的所有状态,0为未访问,1为已访问

void readdata();
void init();
int search();
struct colornode moveahead(struct colornode u);//u向前走一格得到的结点v
struct colornode turntoleft(struct colornode u);//u向左转得到新结点v
struct colornode turntoright(struct colornode u);//u向右转得到新结点v
int islegal(struct colornode v);
int isaim(struct colornode v);
int used(struct colornode v);//判断该点是否是已经到达过的结点
void addtoopen(struct colornode v);//将节点v加入队列
struct colornode takeoutofopen();//从队列头取节点数据
///////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    readdata();
    init();
    int number=search();
    printf("%d\n",number);
    return 0;
}
///////////////////////////////////////////////////////////////////////////////////////
int search()
{
    struct colornode u,v;    
    while(head != tail)
    {
        u = takeoutofopen();//从队列头取数据        
        //////////////////////////////向前走可能到目标
        v = moveahead(u);//向前走        
        if(islegal(v))
        {
            if(isaim(v))
                return(v.num);
            else if(!used(v))
                addtoopen(v);
        }
        //////////////////////////////向左,向右转都不会到目标点
        v=turntoleft(u);//左转        
        if(!used(v))
            addtoopen(v);
        /////////////////////////////
        v=turntoright(u);//右转        
        if(!used(v))
            addtoopen(v);
    }
    return 0;//起始点没有通路时
}
struct colornode turntoright(struct colornode u)
{
    struct colornode v;
    v=u;
    v.direction = (u.direction+3)%4;//只要改变方向    
    v.num = u.num+1;
    return(v);
}
struct colornode turntoleft(struct colornode u)
{
    struct colornode v;    
    v=u;
    v.direction = (u.direction+1)%4;//只要改变方向    
    v.num = u.num+1;    
    return(v);
}
int used(struct colornode v)
{
    if(b[v.row][v.col][v.color][v.direction]==0)
        return 0;
    else
        return 1;
}
int isaim(struct colornode v)
{
    if(v.row==t.row &&v.col==t.col &&v.color==t.color)
        return 1;
    else
        return 0;
}
int islegal(struct colornode v)
{
    if(v.row>=0 &&v.row<n &&v.col>=0 &&v.col<n &&a[v.row][v.col]==0)
        return 1;
    else return 0;
}
struct colornode moveahead(struct colornode u)
{
    struct colornode v;    
    v.row=u.row+direct[u.direction][0];    //由方向决定行列增减值
    v.col=u.col+direct[u.direction][1];    
    v.color = (u.color+1)%5;//颜色循环    
    v.direction = u.direction;//直走方向不变    
    v.num = u.num+1;//新的位置步长加1    
    return(v);
}
struct colornode takeoutofopen()
{
    struct colornode v;
    v=open[head++];
    head=head%openlen;
    return v;
}
void addtoopen(struct colornode v)
{
    open[tail++]=v;    
    tail = tail%openlen;
    b[v.row][v.col][v.color][v.direction]=1;//走过的点状态记为1
}
//////////////////////////////////////////////////////////////////////
void readdata()
{
    char str[50];
    int Berow,Becol;
    char Becolor,Bedir;
    scanf("%d %d %c %c",&Berow,&Becol,&Becolor,&Bedir);//注意%c之前一定要加空格
    s.row = (Berow-1);
    s.col = (Becol-1);
    switch(Becolor)
    {   case 'R':s.color=0;break;//红色块压地,值为0
        case 'Y':s.color=1;break;
        case 'B':s.color=2;break;
        case 'W':s.color=3;break;
        case 'G':s.color=4;break;
    };
    switch(Bedir)
    {    case 'W':s.direction=0;break;//向左,方向值为0
        case 'S':s.direction=1;break;
        case 'E':s.direction=2;break;
        case 'N':s.direction=3;break;
    };
    
    int Enrow,Encol;
    char Encolor;
    scanf("%d %d %c",&Enrow,&Encol,&Encolor);//注意%c之前一定要加空格
    t.row = (Enrow-1);
    t.col = (Encol-1);
    switch(Encolor)
    {    case 'R':t.color=0;break;
        case 'Y':t.color=1;break;
        case 'B':t.color=2;break;
        case 'W':t.color=3;break;
        case 'G':t.color=4;break;
    };
    
    int i=0,j=0;
    for(i=0;i<n;i++)
    {
        scanf("%s",str);//输入一行迷宫字符,再转换成迷宫数字        
        for(j=0;j<n;j++)
        {    if(str[j]=='X')    a[i][j]=1;//1表示墙
        else    a[i][j]=0;//0表示空格
        }    
    }
}
void init()
{
    int i=0,j=0,k=0,l=0;    
    for(i=0;i<n;i++)//
        for(j=0;j<n;j++)//
            for(k=0;k<5;k++)//颜色
                for(l=0;l<4;l++)//方向
                    b[i][j][k][l]=0;//状态
                
    head=0;    tail=0;
    s.num=0;//在初始状态走的步数为0
    addtoopen(s);
}

posted on 2012-07-16 11:41  IThinktan  阅读(938)  评论(0)    收藏  举报

导航