hdu1026 Ignatius and the Princess I(BFS+路徑記錄)

Ignatius and the Princess I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14569    Accepted Submission(s): 4608
Special Judge


Problem Description
The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166's castle. The castle is a large labyrinth. To make the problem simply, we assume the labyrinth is a N*M two-dimensional array which left-top corner is (0,0) and right-bottom corner is (N-1,M-1). Ignatius enters at (0,0), and the door to feng5166's room is at (N-1,M-1), that is our target. There are some monsters in the castle, if Ignatius meet them, he has to kill them. Here is some rules:

1.Ignatius can only move in four directions(up, down, left, right), one step per second. A step is defined as follow: if current position is (x,y), after a step, Ignatius can only stand on (x-1,y), (x+1,y), (x,y-1) or (x,y+1).
2.The array is marked with some characters and numbers. We define them like this:
. : The place where Ignatius can walk on.
X : The place is a trap, Ignatius should not walk on it.
n : Here is a monster with n HP(1<=n<=9), if Ignatius walk on it, it takes him n seconds to kill the monster.

Your task is to give out the path which costs minimum seconds for Ignatius to reach target position. You may assume that the start position and the target position will never be a trap, and there will never be a monster at the start position.
 

Input
The input contains several test cases. Each test case starts with a line contains two numbers N and M(2<=N<=100,2<=M<=100) which indicate the size of the labyrinth. Then a N*M two-dimensional array follows, which describe the whole labyrinth. The input is terminated by the end of file. More details in the Sample Input.
 

Output
For each test case, you should output "God please help our poor hero." if Ignatius can't reach the target position, or you should output "It takes n seconds to reach the target position, let me show you the way."(n is the minimum seconds), and tell our hero the whole path. Output a line contains "FINISH" after each test case. If there are more than one path, any one is OK in this problem. More details in the Sample Output.
 

Sample Input
5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX. 5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX1 5 6 .XX... ..XX1. 2...X. ...XX. XXXXX.
 

Sample Output
It takes 13 seconds to reach the target position, let me show you the way. 1s:(0,0)->(1,0) 2s:(1,0)->(1,1) 3s:(1,1)->(2,1) 4s:(2,1)->(2,2) 5s:(2,2)->(2,3) 6s:(2,3)->(1,3) 7s:(1,3)->(1,4) 8s:FIGHT AT (1,4) 9s:FIGHT AT (1,4) 10s:(1,4)->(1,5) 11s:(1,5)->(2,5) 12s:(2,5)->(3,5) 13s:(3,5)->(4,5) FINISH It takes 14 seconds to reach the target position, let me show you the way. 1s:(0,0)->(1,0) 2s:(1,0)->(1,1) 3s:(1,1)->(2,1) 4s:(2,1)->(2,2) 5s:(2,2)->(2,3) 6s:(2,3)->(1,3) 7s:(1,3)->(1,4) 8s:FIGHT AT (1,4) 9s:FIGHT AT (1,4) 10s:(1,4)->(1,5) 11s:(1,5)->(2,5) 12s:(2,5)->(3,5) 13s:(3,5)->(4,5) 14s:FIGHT AT (4,5) FINISH God please help our poor hero. FINISH

題意:給定m行n列的地圖,“.”表示道路,“1”~“9”表示有怪獸,數值爲打敗怪獸所需時間,“X”表示陷阱,不可走。每走一步需要1s,左上角(0,0)是起點,右下角(n-1,m-1)是終點。要求從起點走到終點的最短時間,並且輸出每一秒的動作(兩點間的移動或是在某一點打怪)。

這道題的代碼我從昨天改到今天,中間發現了一堆奇奇怪怪的錯誤。

一開始是被題目上面的Special Judge”所迷惑,也沒有好好看題,就以爲只要在多種路線中輸出一種就行,所以就用了DFS,然後華麗麗的TLE了,改成BFS之後再交,WA。。重新看題才發現是要求最短時間。

爲了求最少時間,給map[i][j]多定義了一個參數ans來記錄從起點走到點(i,j)所用的最少時間,初始化爲最大值1e9-1。從now的四個不同方向走到next,每走一步都比較一下是否能夠減小next的ans。還把visit數組刪掉了,因爲每個方向都要走一遍,肯定不是每個點只走一次,所以visit數組就沒有意義了。

改完之後樣例過了(樣例一直都能過。。。),就特別開心地交了,還是WA。。。就覺得自己的代碼沒有問題了,就去網上搜各種其他樣例,當然也看了別人的代碼,發現好多都是用的優先隊列,原諒本渣渣還沒有接觸過優先隊列,又固執地認爲自己的算法肯定沒有錯,就只是試各種數據,終於發現一組數據過不了。錯誤是,在BFS裏,當走到終點時,我就直接return了,所以這個代碼實質上還是隻記錄了一種路線,只是在過程中注意了最少時間,結果依舊不是最少的。因此,改代碼,走到終點時不退出BFS,比較記錄的走到終點所用時間跟新走法的時間,然後再繼續走其他方向,直到把所有可能情況走完。

改完交,又WA,我都要絕望了,從頭開始看代碼,發現記錄路徑的數組a[]、b[]開的太小,只開了100,n和m的範圍是100,路徑長度肯定不止100呀,於是索性改成10000。終於AC了。

我的路徑記錄是用兩個數組記錄每一步的橫、縱座標,給map[i][j]定義了一個參數fa來在BFS中記錄是從哪個點走到點(i,j),在輸出前倒序記錄到數組a[]、b[]中。看到網上的其他好多代碼都是用的遞歸輸出,我吧,以前愛用遞歸,覺得代碼簡潔,寫起來也簡單,但是經歷了幾次爆棧之後,就不怎麼敢用了。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

struct pos
{
    int x;
    int y;
    int step;
};

struct maps
{
    char data;
    int ans;
    pos fa;
};

int n,m,cnt;
maps map[105][105];
int a[10005],b[10005];
int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
pos q[1000005];
//bool vis[105][105];

void bfs(int x, int y)
{
    int f = 0,r = 0;
    pos now,next;
    q[r].x = x;
    q[r].y = y;
    q[r++].step = 0;
    map[x][y].ans = 0;
    //vis[x][y] = true;
    while(f != r)
    {
        now = q[f++];
        if(now.x == n - 1 && now.y == m - 1 && map[n - 1][m - 1].ans > now.step)
        {
            map[n - 1][m - 1].ans = now.step;
        }
        for(int i = 0; i < 4; i++)
        {
            next.x = now.x + dir[i][0];
            next.y = now.y + dir[i][1];
            if(next.x >= 0 && next.x < n && next.y >= 0 && next.y < m )
            {
                if(map[next.x][next.y].data == '.' && map[next.x][next.y].ans > now.step + 1)
                {
                    //vis[next.x][next.y] = true;
                    next.step = now.step + 1;
                    map[next.x][next.y].ans = next.step;
                    map[next.x][next.y].fa = now;
                    q[r++] = next;
                }
                else if(map[next.x][next.y].data >= '1' && map[next.x][next.y].data <= '9' && map[next.x][next.y].ans > now.step + map[next.x][next.y].data - '0' + 1)
                {
                    //vis[next.x][next.y] = true;
                    next.step = now.step + map[next.x][next.y].data - '0' + 1;
                    map[next.x][next.y].ans = next.step;
                    map[next.x][next.y].fa = now;
                    q[r++] = next;
                }
            }
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&m) != EOF)
    {
        cnt = 1;
        //memset(vis,false,sizeof(vis));
        for(int i = 0; i < n; i++)
        {
            getchar();
            for(int j = 0; j < m; j++)
            {
                scanf("%c",&map[i][j].data);
                map[i][j].ans = 999999999;
            }
        }
        map[0][0].ans = 0;
        bfs(0,0);
        if(map[n-1][m-1].ans == 999999999)
            printf("God please help our poor hero.\n");
        else
        {
            a[map[n-1][m-1].ans] = n-1;
            b[map[n-1][m-1].ans] = m-1;
            for(int i = map[n-1][m-1].ans; i>0; i--)
            {
                a[i-1] = map[a[i]][b[i]].fa.x;
                b[i-1] = map[a[i]][b[i]].fa.y;
            }
            printf("It takes %d seconds to reach the target position, let me show you the way.\n",map[n-1][m-1].ans);
            for(int i = 1; i <= map[n-1][m-1].ans; i++)
            {
                if(a[i] != 0 || b[i] != 0)
                {
                    printf("%ds:(%d,%d)->(%d,%d)\n",cnt++,a[i-1],b[i-1],a[i],b[i]);
                    if(map[a[i]][b[i]].data >= '1' && map[a[i]][b[i]].data <= '9')
                    {
                        for(int j = 0; j < map[a[i]][b[i]].data - '0'; j++)
                        {
                            printf("%ds:FIGHT AT (%d,%d)\n",cnt++,a[i],b[i]);
                        }
                    }
                }
            }
        }
        printf("FINISH\n");
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章