营救公主

题目描述:

公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。为了使问题简单化,我们假设这个迷宫是一个N*M的二维方格。迷宫里有一些墙,王子不能通过。王子只能移动到相邻(上下左右四个方向)的方格内,并且一秒只能移动一步,就是说,如果王子在(x,y)一步只能移动到(x-1,y),(x+1,y),(x,y-1),(x,y+1)其中的一个位置上。地图由‘S’,‘P’,‘.’,‘*’四种符号构成,‘.’表示王子可以通过,‘*’表示墙,王子不能通过;'S'表示王子的位置;‘P’表示公主的位置;T表示公主存活的剩余时间,王子必须在T秒内到达公主的位置,才能救活公主。如下图所示:

上面是一个5*5的迷宫,红色箭头标识的是从S到P的一条路径。这条路径是最短的一条。如果题目中给的T是5的话,那么就无法救出公主。

解法:

对于这个迷宫问题,广度优先遍历可以找到一条最短的路径。我们把S作为树的根节点,其上下左右的点为孩子节点,那么首先肯定是看看孩子节点里面是不是公主。如果都不是的话,那么就查看某个孩子节点的4个孩子节点是否是公主。这也就是广度优先遍历了。首先我们给每个格子编个号码。然后我们把它变成树看看:

图没画完.......  发现我举的例子有些问题,数据太大了。

大致的树如上图所示,广度优先遍历,找到公主时看一下那时是第几层就就知道最短路径是几步了。那么,怎么维护这个层数呢?初始化时根的层数为0。遍历时,取出当前节点的层数,然后把所有孩子的层数设置为level+1,然后让所有孩子入队列。这样就可以知道找到公主时是第几层了。

代码如下:

 

#ifndef SAVE_PRINCESS_H  
#define SAVE_PRINCESS_H  
  
/* 
 * 公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。 
 * 为了使问题简单化,我们假设这个迷宫是一个N*M的二维方格。迷宫里有一些墙,王子不能通过。王子只 
 * 能移动到相邻(上下左右四个方向)的方格内,并且一秒只能移动一步,就是说,如果王子在(x,y)一步 
 * 只能移动到(x-1,y),(x+1,y),(x,y-1),(x,y+1)其中的一个位置上。地图由‘S’,‘P’,‘.’,‘*’ 
 * 四种符号构成,‘.’表示王子可以通过,‘*’表示墙,王子不能通过;'S'表示王子的位置;‘P’表示公主 
 * 的位置;T表示公主存活的剩余时间,王子必须在T秒内到达公主的位置,才能救活公主。如下图所示: 
 */  
  
/* M行N列迷宫  
 * 如果能够救则返回1, 否则返回0 
 */  
extern int save_princess(int M, int N, char* maze_data, int time);  
  
#endif</span>  

[cpp] view plaincopy
<span style="font-family:Courier New;">#include "save_princess.h"  
#include <string.h>  
#include <stdlib.h>  
#include <stdio.h>  
  
enum DIRECTION  
{  
    D_UP = 0,  
    D_DOWN,  
    D_LEFT,  
    D_RIGHT,  
    D_SIZE  
};  
  
enum ROOM_TYPE  
{  
    TYPE_ROAD,  
    TYPE_WINDOW,  
    TYPE_PRINCE,  
    TYPE_PRINCESS,  
};  
  
struct room_info  
{  
    int row;  
    int col;  
    enum ROOM_TYPE type;  
    int pass_by;  
    struct room_info* child[D_SIZE];  
};  
  
static void init_room(struct room_info* r)  
{  
    memset(r, 0, sizeof(*r));  
}  
  
/*  
 * 返回指向孩子的指针,孩子为墙则返回NULL 
 * M*N 的迷宫,max_row = M - 1, max_col = N - 1 
 */  
static struct room_info* get_child(struct room_info* maze, int max_row, int max_col,   
                       struct room_info* cur_room, enum DIRECTION direct)  
{  
    int row = 0;  
    int col = 0;  
    int idx = 0;  
    struct room_info* child = NULL;  
  
    if (NULL == maze  
        || NULL == cur_room)  
    {  
        return NULL;  
    }  
      
    row = cur_room->row;  
    col = cur_room->col;  
  
    switch (direct)  
    {  
    case D_UP:  
        if (row <= 0)  
        {  
            return NULL;  
        }  
  
        row--;  
        break;  
    case D_DOWN:  
        if (row >= max_row)  
        {  
            return NULL;  
        }  
        row++;  
  
        break;  
    case D_LEFT:  
        if (col <= 0)  
        {  
            return NULL;  
        }  
        col--;  
  
        break;  
    case D_RIGHT:  
        if (col >= max_col)  
        {  
            return NULL;  
        }  
        col++;  
  
        break;  
    default:  
        break;  
    }  
  
    idx = row * (max_col + 1) + col;  
  
    child = maze + idx;  
    if (TYPE_WINDOW == child->type)  
    {  
        return NULL;  
    }  
    else  
    {  
        return child;  
    }  
}  
  
/* 成功返回指向S的指针, 失败返回NULL*/  
static struct room_info* init_maze(struct room_info* maze, int M, int N, char* maze_data)  
{  
    int row = 0;  
    int col = 0;  
    struct room_info* prince = NULL;  
  
    /* 第一遍识别墙等,确定坐标 */  
    for (row = 0; row < M; row++)  
    {  
        for (col = 0; col < N; col++)  
        {  
            int idx = row * N + col;  
            char c = *(maze_data + idx);  
  
            init_room(maze + idx);  
  
            maze[idx].row = row;  
            maze[idx].col = col;  
  
            switch (c)  
            {  
            case '.':  
                maze[idx].type = TYPE_ROAD;  
                break;  
            case '*':  
                maze[idx].type = TYPE_WINDOW;  
                break;  
            case 'S':  
                prince = maze + idx;  
                maze[idx].type = TYPE_PRINCE;  
                break;  
            case 'P':  
                maze[idx].type = TYPE_PRINCESS;  
                break;  
            default:  
                return NULL;  
            }  
        }  
    }  
  
    /*第二遍建立图*/  
    for (row = 0; row < M; row++)  
    {  
        for (col = 0; col < N; col++)  
        {  
            int idx = row * N + col;  
  
            maze[idx].child[D_UP]   = get_child(maze, M - 1, N - 1, maze + idx, D_UP);  
            maze[idx].child[D_DOWN] = get_child(maze, M - 1, N - 1, maze + idx, D_DOWN);  
            maze[idx].child[D_LEFT] = get_child(maze, M - 1, N - 1, maze + idx, D_LEFT);  
            maze[idx].child[D_RIGHT]= get_child(maze, M - 1, N - 1, maze + idx, D_RIGHT);  
        }  
    }  
  
    return prince;  
}  
  
struct node_info  
{  
    int level;  
    struct room_info* room;  
    struct node_info* parent;  
  
    struct node_info* next;  
};  
  
static void init_node_info(struct node_info* info)  
{  
    memset(info, 0, sizeof(*info));  
}  
  
static void queue_push(struct node_info* queue,   
                        struct room_info* room,   
                        int cur_level,   
                        struct node_info* parent)  
{  
    struct node_info* new_node = NULL;  
  
    if (NULL == room)  
    {  
        return;  
    }  
  
    new_node = (struct node_info*)malloc(sizeof(struct node_info));  
    init_node_info(new_node);  
      
    new_node->level = cur_level + 1;  
    new_node->parent = parent;  
    new_node->room = room;  
  
    while (queue != NULL)  
    {  
        if (NULL == queue->next)  
        {  
            queue->next = new_node;  
            break;  
        }  
  
        queue = queue->next;  
    }  
}  
  
static void queue_release(struct node_info* queue)  
{  
    struct node_info* tmp = NULL;  
    while (queue != NULL)  
    {  
        tmp = queue->next;  
        free(queue);  
          
        queue = tmp;  
    }  
}  
  
/* 找到princess返回需要的步数 
 * 找不到或者出错返回-1 
 */  
static int find_princess(struct room_info* maze, struct room_info* prince)  
{  
    struct node_info* queue =  NULL;  
    struct node_info* cur_step =  NULL;  
  
    queue = (struct node_info*)malloc(sizeof(struct node_info));  
    if (NULL == queue)  
    {  
        return -1;  
    }  
  
    init_node_info(queue);  
    queue->parent = NULL;  
    queue->level = 0;  
    queue->room = prince;  
  
    cur_step = queue;  
    while (cur_step != NULL)  
    {  
        struct room_info* cur_room = cur_step->room;  
        if (NULL == cur_room)  
        {  
            fprintf(stderr, "IT CAN NOT HAPPEN!\n");  
            break;  
        }  
  
        if (TYPE_PRINCESS == cur_room->type)  
        {  
            struct node_info* tmp = cur_step;  
            /* we find princess :) */  
            fprintf(stdout, "\nThe way back to prince... \n");  
            while (tmp != NULL)  
            {  
                fprintf(stdout, "(%d, %d) ", tmp->room->row, tmp->room->col);  
  
                tmp = tmp->parent;  
            }  
            fprintf(stdout, "\n");  
  
            queue_release(queue);  
            return cur_step->level;  
        }  
        else if (TYPE_ROAD == cur_room->type  
                || TYPE_PRINCE == cur_room->type)  
        {  
            struct room_info* tmp = NULL;  
  
            if (1 == cur_room->pass_by)  
            {  
                cur_step = cur_step->next;  
                continue;  
            }  
  
            cur_room->pass_by = 1;  
  
            /* 把孩子们丢到队列后面 */  
            tmp = cur_room->child[D_UP];  
            queue_push(queue, tmp, cur_step->level, cur_step);  
  
            tmp = cur_room->child[D_DOWN];  
            queue_push(queue, tmp, cur_step->level, cur_step);  
  
            tmp = cur_room->child[D_LEFT];  
            queue_push(queue, tmp, cur_step->level, cur_step);  
  
            tmp = cur_room->child[D_RIGHT];  
            queue_push(queue, tmp, cur_step->level, cur_step);  
        }  
        else   
        {  
            fprintf(stderr, "Wired!\n");  
        }  
  
        cur_step = cur_step->next;  
    }  
  
    queue_release(queue);  
    return -1;  
}  
  
int save_princess(int M, int N, char* maze_data, int time)  
{  
    struct room_info* maze = NULL;  
    struct room_info* prince = NULL;  
    int time_need = 0;  
  
    if (M <= 1  
        || N <= 1  
        || NULL == maze_data  
        || 0 == time)  
    {  
        return 0;  
    }  
  
    maze = (struct room_info*)malloc(M * N * sizeof(struct room_info));  
    if (NULL == maze)  
    {  
        return 0;  
    }  
  
    prince = init_maze(maze, M, N, maze_data);  
    if (NULL == prince)  
    {  
        /*输入数据有误*/  
        return 0;  
    }  
  
    time_need = find_princess(maze, prince);  
    if (-1 == time_need)  
    {  
        return 0;  
    }  
    else if (time_need > time)  
    {  
        return 0;  
    }  
    else  
    {  
        return 1;  
    }  
}</span>  

[cpp] view plaincopy
<span style="font-family:Courier New;">#include "save_princess.h"  
#include <stdio.h>  
  
#define M 10  
#define N 10  
  
int main()  
{  
    int ret = 0;  
    int row = 0;  
    int col = 0;  
  
    char maze_info[M][N] = {\  
    /*      0    1    2    3    4    5    6    7    8    9*/  
    /*0*/ {'.', '.', '.', '*', '.', '.', '.', '.', '.', '.'},  
    /*1*/ {'.', 'S', '*', '.', '.', '.', '.', '.', '.', '.'},  
    /*2*/ {'.', '.', '*', '.', '.', '.', '.', '.', '.', '.'},  
    /*3*/ {'.', '.', '*', '*', '.', '*', '.', '.', '.', '.'},  
    /*4*/ {'.', '.', '.', '*', '.', '*', '.', '.', '.', '.'},  
    /*5*/ {'.', '.', '.', '*', '.', '.', '.', '.', '.', '.'},  
    /*6*/ {'.', '.', '*', '.', '.', '.', '.', '.', '.', '.'},  
    /*7*/ {'.', '.', '*', '.', '*', '.', '*', '.', '.', '.'},  
    /*8*/ {'.', '.', '.', '.', '*', '.', '*', '*', '*', '.'},  
    /*9*/ {'.', '.', '*', '.', '*', '.', '*', 'P', '.', '.'}};  
  
    fprintf(stdout, "\n  ");  
    for (col = 0; col < N; col++)  
    {  
        fprintf(stdout, "%d ", col);  
    }  
    fprintf(stdout, "\n");  
  
    for (row = 0; row < M; row++)  
    {  
        fprintf(stdout, "%d ", row);  
        for (col = 0; col < N; col++)  
        {  
            fprintf(stdout, "%c ", maze_info[row][col]);  
        }  
        fprintf(stdout, "\n");  
    }  
  
    ret = save_princess(M, N, (char*)maze_info, 6);  
  
    fprintf(stdout, "\n");  
    system("pause");  
    return 0;  
}


原链接:http://wenku.baidu.com/view/4dc3fa830029bd64783e2c37.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值