(intermediate) UVA 10358 Matrix

Problem F

Matrix

Input: standard input

Output: standard output

Time Limit: 4 seconds

Memory Limit: 32 MB

The year is close to 2200 and machines with supreme artificial intelligence have conquered the world. Fortunately, the humans are still kept alive since they provide a good energy source for the machines. However, in order to keep mankind neutralized, most people are trapped in a computer program called the Matrix designed to simulate the 20th century, and thereby unaware of the 'real' world. Still, a few people like yourself have been released from the Matrix and others have even been born free. Together we try to fight the machines. The Oracle has spoken about one man who will save mankind, and the people outside the Matrix must enter it from time to time in order to try to find this chosen one. It is hazardous to enter though. The only way out of the Matrix is by being phoned from the outside on a stationary phone inside and there are supernatural agents in the Matrix who try to eliminate all trespassers. Everyone who has been caught by an agent so far has died, so the best thing to do when you encounter one is to run. Since the Matrix is a computer program, the agents know of your whereabouts all the time when you are inside it. On the other hand you know the location of the agents too, since the people helping you from outside the Matrix scan it and tell you what they see. You move at the same speed as the agents since you have learned to control the laws of the program. You want to know for a few scenarios if you would be able to escape the Matrix or if you would be caught by the agents, so you design a program. For simplicity, the Matrix is modelled by a two-player boardgame on an 8 by 8 square board with you and two agents as pieces. There are three kinds of squares: floor squares, wall squares and phone squares. A piece may be located on any square except the wall squares, even if the square is already occupied by another piece. The simulation begins by a move by you. Then the two agents move and after that it is your turn to move again. This moving scheme continues to alternate until either your piece gets to a vacant phone square which means that you succeed in escaping the Matrix, or until at least one of the agent pieces is on the same square as your piece, in which case you are captured, and thereby eliminated. A third outcome is possible if neither of the two breaking conditions mentioned above occurs. In that case you are said to be trapped in the Matrix. A move of a piece constitutes of moving the piece located at square (x,y) to one of (x,y),(x+1,y),(x-1,y),(x,y-1), or (x,y+1) that is not a wall square.

Input

The input consists of several scenarios. For each scenario you are to determine whether the agent pieces cannot be sure to prevent you from escaping the Matrix despite how hard they try, or whether you cannot be certain to stop the agents from eliminating you. The first line of input is a positive number n. Then follow n scenarios, each consisting of 8 rows of 8 characters each from the set {'.','#','P','A','M'} describing the Matrix board. A '.'-charactersymbolizes a floor square, a '#'-character a wall square and a 'P'-character a phone square. There are exactly two 'A'-characters in each scenario indicating the starting positions of the two agents, and exactly one 'M'-character giving your position in the Matrix. The initial squares of the three pieces are all floor squares. At least half of the 64 squares are wall squares for all scenarios. All scenarios, including the last one, end with a blank line.

Output

For each scenario, there should be one line of output. If your piece can escape the Matrix regardless of the efforts made by the agents to stop you, the text 'You can escape.' should be printed. If the agent pieces may capture you whatever moves your piece make, you are eliminated and the text 'You are eliminated.' should be printed. If neither of the two conditions described above are true, the text 'You are trapped in the Matrix.' should be printed.

Sample Input

3
#####.##
#####.##
#####.##
AA.M...P
#####.##
#####.##
#####.##
#####.##
 
########
#..P...#
#.####.#
#P#M.#P#
#.####.#
#..P...#
#A....A#
########
 
########
#...A.P#
#.######
#..M...#
#.####.#
..####..
#....A.#
########

Sample Output

You can escape.
You are trapped in the Matrix.
You are eliminated.
 
 

Andreas Björklund



题意:有一个迷宫,有一个点M是自己,A点是特工,P点是电话亭,你需要到达电话亭逃出去。问你能不能逃出去,或者是不是一定会被消灭,或者都不是。


思路:由于这里会有环,所以我们不能正着推状态的“好”“坏”,所以我们只能从终止节点开始往前推,假设0代表必输,1代表必赢,那么从0开始推到的所有状态都是必赢的,如果一个点到达的状态都是必赢的,那么这个点就是必输的,但是这个情况要怎么求呢?我们事先求出一个状态能转移到多少个状态,那么在倒推的时候,如果有一个1状态能推出这个状态,就将这个能转移的状态数-1,直到为0,那么这个点就是必输的。


代码:

#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <string.h>
using namespace std;
#define LL long long
#define clr(a,x) memset(a,x,sizeof(a))
const int maxn=100000+5;
char maze[10][10];
int win[2][66][66][66];
int deg[2][66][66][66];
const int Move[2][5]={{-1,0,1,0,0},{0,1,0,-1,0}};
inline int getx(int r,int c) { return r*8+c; }
inline int row(int x) { return x/8; }
inline int col(int x) { return x%8; }
bool inRange(int r,int c) { return 0<=r&&r<8&&0<=c&&c<8; }
int M,A1,A2;

int emt[66],c;
void input()
{
    for(int i=0;i<8;++i) scanf("%s",maze[i]);
    M=A1=A2=-1;
    for(int i=0;i<8;++i) for(int j=0;j<8;++j)
    {
        if(maze[i][j]=='M') M=getx(i,j);
        else if(maze[i][j]=='A') {
            if(A1==-1) A1=getx(i,j);
            else A2=getx(i,j);
        }
    }
    clr(deg,0); c=0;
    for(int i=0;i<8;++i) for(int j=0;j<8;++j)
    {
        if(maze[i][j]=='#') continue;
        emt[c++]=getx(i,j);
    }
    clr(win,-1);
    for(int i=0;i<c;++i) for(int j=0;j<c;++j) for(int k=0;k<c;++k)
    {
        int x=emt[i],y=emt[j],z=emt[k];
        int r=row(x),c=col(x);
        if(maze[r][c]=='P') {
            if(x==y||x==z) win[1][x][y][z]=1;
            else  win[0][x][y][z]=1,win[1][x][y][z]=0;
        } else if(x==y||x==z) win[0][x][y][z]=0,win[1][x][y][z]=1;
        else {
            for(int d=0;d<5;++d) {
                int rr=r+Move[0][d];
                int cc=c+Move[1][d];
                if(!inRange(rr,cc)||maze[rr][cc]=='#') continue;
                ++deg[0][x][y][z];
            }
            r=row(y),c=col(y);
            int r1=row(z),c1=col(z);
            for(int d=0;d<5;++d) {
                int rr=r+Move[0][d];
                int cc=c+Move[1][d];
                if(!inRange(rr,cc)||maze[rr][cc]=='#') continue;
                for(int dd=0;dd<5;++dd) {
                    int rr1=r1+Move[0][dd];
                    int cc1=c1+Move[1][dd];
                    if(!inRange(rr1,cc1)||maze[rr1][cc1]=='#') continue;
                    ++deg[1][x][y][z];
                }
            }
        }
    }
}

struct State
{
    int m,a1,a2,player;
    State(int m=0,int a1=0,int a2=0,int player=0)
    :m(m),a1(a1),a2(a2),player(player) { }
};

void solve()
{
    queue<State> q;
    for(int i=0;i<c;++i) for(int j=0;j<c;++j) for(int k=0;k<c;++k)
    {
        int x=emt[i],y=emt[j],z=emt[k];
        if(win[0][x][y][z]!=-1) q.push(State(x,y,z,0));
        if(win[1][x][y][z]!=-1) q.push(State(x,y,z,1));
    }
    int c_m=26,c_a1=25,c_a2=25,c_p=0;
    while(q.size()) {
        State t=q.front(); q.pop();
        int p=t.player,m=t.m,a1=t.a1,a2=t.a2;
        if(p==1) {
            int r=row(m),c=col(m);
            assert(win[p][m][a1][a2]!=-1);
            if(win[p][m][a1][a2]==0) {
                for(int d=0;d<5;++d) {
                    int rr=r+Move[0][d];
                    int cc=c+Move[1][d];
                    if(!inRange(rr,cc)||maze[rr][cc]=='#') continue;
                    int y=getx(rr,cc);
                    assert(win[p^1][a1][a2]!=0);
                    if(win[p^1][y][a1][a2]==-1) {
                        win[p^1][y][a1][a2]=1;
                        q.push(State(y,a1,a2,p^1));
                    }
                }
            }
            else if(win[p][m][a1][a2]==1)
            {
                for(int d=0;d<5;++d) {
                    int rr=r+Move[0][d];
                    int cc=c+Move[1][d];
                    if(!inRange(rr,cc)||maze[rr][cc]=='#') continue;
                    int y=getx(rr,cc);
                    if(win[p^1][y][a1][a2]==-1) {
                        --deg[p^1][y][a1][a2];
                        if(deg[p^1][y][a1][a2]==0)
                        {
                            q.push(State(y,a1,a2,p^1));
                            win[p^1][y][a1][a2]=0;
                        }
                    }
                }
            }
        }
        else {
            int r1=row(a1),c1=col(a1);
            int r2=row(a2),c2=col(a2);
            for(int d=0;d<5;++d) {
                int rr1=r1+Move[0][d];
                int cc1=c1+Move[1][d];
                if(!inRange(rr1,cc1)||maze[rr1][cc1]=='#') continue;
                int y=getx(rr1,cc1);
                for(int dd=0;dd<5;++dd) {
                    int rr2=r2+Move[0][dd];
                    int cc2=c2+Move[1][dd];
                    if(!inRange(rr2,cc2)||maze[rr2][cc2]=='#') continue;
                    int z=getx(rr2,cc2);
                    if(win[p][m][a1][a2]==0) {
                        assert(win[p^1][m][y][z]!=0);
                        if(win[p^1][m][y][z]==-1) {
                            win[p^1][m][y][z]=1;
                            q.push(State(m,y,z,p^1));
                        }
                    } else if(win[p^1][m][y][z]==-1) {
                        --deg[p^1][m][y][z];
                        if(deg[p^1][m][y][z]==0) {
                            win[p^1][m][y][z]=0;
                            q.push(State(m,y,z,p^1));
                        }
                    }
                }
            }
        }
    }
    if(win[0][M][A1][A2]==1) puts("You can escape.");
    else if(win[0][M][A1][A2]==0) puts("You are eliminated.");
    else puts("You are trapped in the Matrix.");
}

int main()
{
    int T;cin>>T;
    while(T--) {
        input();
        solve();
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值