WUSTOJ-2245: Twilight Princess(BFS)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82178611

2245: Twilight Princess
Time Limit: 10 Sec Memory Limit: 256 MB 64bit IO Format: %lld

Description
In the Legend of Zelda : Twilight Princess, deep within the Faron Province and adjacent to the Forest Temple entrance, is the Sacred Grove, an ancient forest that not only holds strong ties to the Royal Family and the Sages, but also protects the Master Sword from outsiders. Before cntering the final forested area where the Master Sword is hidden, one last puzzle awaits. The two guards that oversee the old Door of Time have dislocated themselves and expect Wolf Link to place them in their respective positions again.
Particularly, the puzzle is on board with N×M cells. Some cells of the board are clear, while the others are blocked. We name our controllable hero Link and the two guards A and B. All three of them can move to an adjacent clear cell per move. It is worth noticing that the two guards action according to the action of Link. When Link moves East/West/North/South, Guard A will move East/West/North/South and Guard B will move West/East/South/North. If the cell to which the guard is going to move is blocked, the guard will hurt Link by one Health Point (HP) and then simply stay on the original cell. If the two guards hurt Link at the same time, Link’s HP will only be reduced by one point. It is worth noticing that Link and the two guards will neither be on the same cell nor swap the positions (or they will collide in the air) after each move.
Here comes your problem. Given the original positions and total HP of Link, find the minimum moves to let the two guards place themselves in their respective positions at the same time before Link’s HP becoming zero.
Input
There are multiple test data sets.
In each test data set, the first line contains three integers N , M ( 1 N , M l 00 ) and H P ( 1 H P 10 ) representing the number of rows and columns of the board, and the original HP of Link.
N lines follow, each line contains M characters, representing the types of the cells.
① ‘.’ for clear cell.
② ‘X’ for blocked cell.
③ ‘L’, ‘a’, ‘b’ for the initial positions of Link, Guard A and Guard B. The cells they standing on are clear.
④ ‘A’, ‘B’ for the destinations for Guard A and Guard B. The cells are clear as well.
The input is terminated by EOF.
Output
For each test data set, output one line containing the minimum number of moves or “impossible” if there is no solution.
Sample Input
6 5 7
..X..
.AbB.
…..
X.L.X
X…X
XXaXX
6 5 6
..X..
.AbB.
…..
X.L.X
X…X
XXaXX
3 5 10
a.A..
XXXXX
BLb..

Sample Output
12
impossible
impossible

HINT
For the first sample input test case, here is an optimal solution which represents the movements of Link.
这里写图片描述

题解:因为HP<=10,所以对人物行走的限制条件还是很大的,那么可行的状态数不是非常的多,可以直接用BFS,判重用set(我用Hash写T了,估计Hash写丑了。。)。

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int MOD=1e9+7;
const int Hashsize=1e5+3;
const double PI=acos(-1.0);
typedef long long ll;
char s[110][110];
int n,m;
struct Point{int x,y;}d[4];
Point operator+(Point A,Point B){return (Point){A.x+B.x,A.y+B.y};}
Point operator-(Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
bool operator==(const Point&A,const Point&B){return A.x==B.x&&A.y==B.y;}
struct status
{
    Point L,A,B;
    int HP,step;
    int operator < (const status & rhs) const
    {
        if (L.x != rhs.L.x) return L.x < rhs.L.x;
        if (L.y != rhs.L.y) return L.y < rhs.L.y;
        if (A.x != rhs.A.x) return A.x < rhs.A.x;
        if (A.y != rhs.A.y) return A.y < rhs.A.y;
        if (B.x != rhs.B.x) return B.x < rhs.B.x;
        if (B.y != rhs.B.y) return B.y < rhs.B.y;
        return false;
    }
};
int out(Point p){return p.x<0||p.x>=n||p.y<0||p.y>=m||s[p.x][p.y]=='X';}
set<status>Hash;
Point Aend,Bend;
int bfs(Point L,Point A,Point B,int HP)
{
    Hash.clear();
    queue<status>p;
    p.push({L,A,B,HP,0});
    Hash.insert({L,A,B,HP,0});
    while(!p.empty())
    {
        status cur=p.front();p.pop();
        for(int i=0;i<4;i++)
        {
            Point nowL=cur.L+d[i];
            Point nowA=cur.A+d[i];
            Point nowB=cur.B-d[i];
            int nowHP=cur.HP;
            if(out(nowL))continue;          //L走出边界或碰到障碍
            if(out(nowA))nowA=cur.A;        //A走出边界或碰到障碍
            if(out(nowB))nowB=cur.B;        //B走出边界或碰到障碍
            if(nowA==nowB)continue;         //A B走到同一位置
            if(nowA==nowL)continue;         //A L走到同一位置
            if(nowB==nowL)continue;         //B L走到同一位置
            if(nowA==cur.B&&nowB==cur.A)continue;//A B互换位置
            if(nowA==cur.L&&nowL==cur.A)continue;//A L互换位置
            if(nowB==cur.L&&nowL==cur.B)continue;//L B互换位置
            if(nowA==cur.A||nowB==cur.B)nowHP--;
            if(nowHP<=0)continue;
            if(Hash.count({nowL,nowA,nowB,nowHP,cur.step+1}))continue;
            if(nowA==Aend&&nowB==Bend)return cur.step+1;
            Hash.insert({nowL,nowA,nowB,nowHP,cur.step+1});
            p.push({nowL,nowA,nowB,nowHP,cur.step+1});
        }
    }
    return -1;
}
int main()
{
    d[0]={-1,0};
    d[1]={0,-1};
    d[2]={1,0};
    d[3]={0,1};
    int HP;
    while(scanf("%d%d%d",&n,&m,&HP)!=EOF)
    {
        for(int i=0;i<n;i++)scanf("%s",s[i]);
        Point L,A,B;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(s[i][j]=='L')L=(Point){i,j};
                if(s[i][j]=='a')A=(Point){i,j};
                if(s[i][j]=='b')B=(Point){i,j};
                if(s[i][j]=='A')Aend=(Point){i,j};
                if(s[i][j]=='B')Bend=(Point){i,j};
            }
        }
        int ans=bfs(L,A,B,HP);
        if(ans==-1)puts("impossible");
        else printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/82178611
BFS