题目叙述
War chess is hh’s favorite game:
In this game, there is an N * M battle map, and every player has his own Moving Val (MV). In each round, every player can move in four directions as long as he has enough MV. To simplify the problem, you are given your position and asked to output which grids you can arrive.
In the map:
‘Y’ is your current position (there is one and only one Y in the given map).
‘.’ is a normal grid. It costs you 1 MV to enter in this gird.
‘T’ is a tree. It costs you 2 MV to enter in this gird.
‘R’ is a river. It costs you 3 MV to enter in this gird.
‘#’ is an obstacle. You can never enter in this gird.
‘E’s are your enemies. You cannot move across your enemy, because once you enter the grids which are adjacent with ‘E’, you will lose all your MV. Here “adjacent” means two grids share a common edge.
‘P’s are your partners. You can move across your partner, but you cannot stay in the same grid with him final, because there can only be one person in one grid.You can assume the Ps must stand on ‘.’ . so ,it also costs you 1 MV to enter this grid.
算法思路
- 很显然的BFS搜索,但是从这一题而言,我们可以看出一些事情。
- 只是使用布尔数组来标记走过的路显然是不行的。我们扩展的点是存在优先级的。也就是说,经过结点数目更多的路径反而消耗的能量要少。
- 所以,我们记录下到达某个节点的时候剩下能量最多的个数,使用队列来进行BFS搜索,显然,队列当中存在多个相同的结点是没有意义的。所以我们再记录下当前的结点是否在队列当中。
- 突然之间,我们发现,这就是我们接触过的spfa算法。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 105
#define INF 0x3f3f3f3f
int movex[4] = {1,-1,0,0};
int movey[4] = {0,0,1,-1};
struct status{
int curx,cury;
status(){}
status(int a,int b){
curx = a;
cury = b;
}
};
char grid[MAXN][MAXN];
int visited[MAXN][MAXN];
bool inQueue[MAXN][MAXN];
int r,c,mv,t;
int stx,sty;
bool adjenermy(int x,int y)
{//judge if the person is next to the
// enermy
if(x>0&&grid[x-1][y]=='E')return true;
if(y>0&&grid[x][y-1]=='E')return true;
if(x<r-1&&grid[x+1][y]=='E')return true;
if(y<c-1&&grid[x][y+1]=='E')return true;
return false;
}
int mustcost(char c)
{//comoute the cost of the step
if(c=='.')return 1;
if(c=='T')return 2;
if(c=='R')return 3;
if(c=='P')return 1;
else return INF;
}
bool Judge(int x,int y,int mvl)
{//judge if the step is available
if(x<0||y<0||x>=r||y>=c)return false;
if(mvl - mustcost(grid[x][y])<0)return false;
else if(grid[x][y]=='P'&&mvl==1)return false;
return true;
}
void print()
{//print the final answer
int i,j;
for(i=0;i<r;i++){
for(j=0;j<c;j++){
if(grid[i][j]=='#'||grid[i][j]=='P'||grid[i][j]=='Y'||visited[i][j]<0)
printf("%c",grid[i][j]);
else
printf("*");
}
printf("\n");
}
printf("\n");
}
void Solve()
{//solve the question with SPFA
int i;
memset(visited,-1,sizeof(visited));
memset(inQueue,false,sizeof(inQueue));
visited[stx][sty] = mv;
queue<status>Q;
status st = status(stx,sty);
Q.push(st);
inQueue[stx][sty] = true;
while(!Q.empty()){
status cur = Q.front();
Q.pop();
inQueue[cur.curx][cur.cury] = false;
//judgr if the current position is next to
//thr enermy
if(adjenermy(cur.curx,cur.cury)&&grid[cur.curx][cur.cury]!='Y')continue;
for(i=0;i<4;i++){
if(Judge(cur.curx+movex[i],cur.cury+movey[i],visited[cur.curx][cur.cury])){
char c = grid[cur.curx+movex[i]][cur.cury+movey[i]];
status next = status(cur.curx+movex[i],cur.cury+movey[i]);
int temp = visited[cur.curx][cur.cury]-mustcost(c);
if(temp > visited[next.curx][next.cury]){
visited[next.curx][next.cury] = temp;
if(!inQueue[next.curx][next.cury]){
Q.push(next);
inQueue[next.curx][next.cury] = true;
}
}
}
}
}
print();
}
int main()
{
freopen("input","r",stdin);
int i,j;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&r,&c,&mv);
for(i=0;i<r;i++){
scanf("%s",grid[i]);
for(j=0;j<c;j++){
if(grid[i][j] == 'Y'){
stx = i;
sty = j;
}
}
}
Solve();
}
return 0;
}