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();
}
}