25.进圈

Description

龙龙最近迷上了一款名叫 PUBG(PLAYERUNKNOWN’S BATTLEGROUNDS)的手游,那是一款关乎生存挑战的 RPG 逃亡游戏。
考虑到游戏的环节过于复杂,龙龙决定简化一下场景:整个地图可以看做一个长为 n n n ​ 宽为 m m m​ 的二维格点平面。龙龙需要从 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) 逃亡到 ( x 2 , y 2 ) (x_2,y_2) (x2,y2) 以逃离毒圈,但有些格点上存在障碍#不能行走,有些格点是沙地.。龙龙只能移动在允许行走的沙地上,同时每一时刻,龙龙只能朝着当前位置周围的上、下、左、右四个方向移动。同时因为龙龙使用了能量饮料,每分钟最多可以朝着一个方向行走 k k k
毒圈快要来啦,请你帮龙龙尽快安排一下可行的路线,使得它能够以最短的时间顺利进圈。

Input

第一行输入三个正整数 n , m n, m n,m k k k ( 1 ≤ n , m , k ≤ 1000 ) (1 \leq n, m, k \leq 1000) (1n,m,k1000) 表示地图的大小还有龙龙每分钟最多可以移动的步数;
接下来 n n n 行,每行包含 m m m 个字符,其中第 i i i行第 j j j 个字符表示坐标 ( i , j ) (i,j) (i,j) 的路况,它可能是#,这表示这个格点是障碍区,不能行走,也可能是.表示沙地;
最后一行输入四个正整数 x 1 , y 1 , x 2 , y 2 x_1, y_1, x_2, y_2 x1,y1,x2,y2 由空格间隔开,表示龙龙的初始位置和目标位置。

Output

请输出一个正整数 t t t,表示龙龙从 ( x 1 , y 1 ) (x_1, y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2)进圈最少需要的时间(分钟),如果龙龙最终不能进圈,则请输出 − 1 -1 1

Hint

对于样例,龙龙第一分钟走 4 4 4 步,从 ( 1 , 3 ) (1, 3) (1,3) ( 1 , 1 ) (1, 1) (1,1) ,第二分钟从 ( 1 , 1 ) (1, 1) (1,1) ( 3 , 1 ) (3, 1) (3,1),第三分钟从 ( 3 , 1 ) (3, 1) (3,1) 走到 ( 3 , 3 ) (3, 3) (3,3) 顺利进圈。

测试输入 期待的输出
3 4 4 . . . . . # # # . . . . 1 3 3 3 \begin{matrix}3&4&4&\\ . & . & . & .\\ . & \# & \# & \#\\ . & . & . & .\\ 1 & 3 & 3 & 3\\\end{matrix} 3...14.#.34.#.3.#.3 3↵

思路

本题和 22.地下城与勇士 还是有很大的相似度,甚至因为去除了时间还要稍微简单一点。对于某一点(i,j),需要分别从上下左右四个方向,移动 1 ~ k 1 \verb|~| k 1~k步。如果越界或碰墙,break;如果访问过,continue;否则就入队列,visited++。注意题目坐标是从 1 1 1开始,变一下。其他就和22题完全一样了。

代码

#include 
#include 
#define N 1010
char map[N][N];
int visited[N][N], n, m, k, x, y;
struct Queue
{
    int zb[N*N][2];
    int time[N*N];
    int front;
    int rear;
} queue;
void init()
{
    memset(visited, 0, sizeof(visited));
    memset(queue.zb, -1, sizeof(queue.zb));
    memset(queue.time, -1, sizeof(queue.time));
    queue.front = 0;
    queue.rear = 0;
}
void push(int i, int j, int t)
{
    queue.zb[queue.rear][0] = i;
    queue.zb[queue.rear][1] = j;
    queue.time[queue.rear] = t;
    queue.rear++;
}
void pop()
{
    queue.front++;
}
int isOK(int i, int j)
{
    if (i < 0 || i >= n || j < 0 || j >= m)
        return 0;
    else if (map[i][j] == '#')
        return 0;
    else if (map[i][j] == '.' && visited[i][j] == 0)
        return 1;
    else
        return -1;
}

int main()
{
    int k, i, j, step, p, q;
    scanf("%d %d %d", &n, &m, &k);
    for (i = 0; i < n; i++)
    {
        scanf("%s", map[i]);
    }
    scanf("%d %d %d %d", &p, &q, &x, &y);
    x--;
    y--;
    init();
    push(p-1, q-1, 0);
    while (1)
    {
        pop();
        int t = queue.time[queue.front - 1] + 1;
        i = queue.zb[queue.front - 1][0];
        j = queue.zb[queue.front - 1][1];
        if(t==0){
        	printf("-1\n");
        	return 0;
		}	      
        // up
        for (step = 1; step <= k; step++)
        {
            if (i == x && j + step == y)
            {
                printf("%d\n", t);
                return 0;
            }

            int flag = isOK(i, j + step);
            if (flag == -1)
                continue;
            else if (flag == 1)
            {
                push(i, j + step, t);
                visited[i][j + step] = 1;
            }
            else
                break;
        }
        // down
        for (step = 1; step <= k; step++)
        {
            if (i == x && j - step == y)
            {
                printf("%d\n", t);
                return 0;
            }

            int flag = isOK(i, j - step);
            if (flag == -1)
                continue;
            else if (flag == 1)
            {
                push(i, j - step, t);
                visited[i][j - step] = 1;
            }
            else
                break;
        }
        // left
        for (step = 1; step <= k; step++)
        {
            if (i - step == x && j == y)
            {
                printf("%d\n", t);
                return 0;
            }

            int flag = isOK(i - step, j);
            if (flag == -1)
                continue;
            else if (flag == 1)
            {
                push(i - step, j, t);
                visited[i - step][j] = 1;
            }
            else
                break;
        }
        // right
        for (step = 1; step <= k; step++)
        {
            if (i + step == x && j == y)
            {
                printf("%d\n", t);
                return 0;
            }

            int flag = isOK(i + step, j);
            if (flag == -1)
                continue;
            else if (flag == 1)
            {
                push(i + step, j, t);
                visited[i + step][j] = 1;
            }
            else
                break;
        }
    }
}

你可能感兴趣的:(程序设计与方法实践小学期,算法,c语言)