hdu3345[BFS和SPFA]

题目叙述

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.

算法思路

  1. 很显然的BFS搜索,但是从这一题而言,我们可以看出一些事情。
  2. 只是使用布尔数组来标记走过的路显然是不行的。我们扩展的点是存在优先级的。也就是说,经过结点数目更多的路径反而消耗的能量要少。
  3. 所以,我们记录下到达某个节点的时候剩下能量最多的个数,使用队列来进行BFS搜索,显然,队列当中存在多个相同的结点是没有意义的。所以我们再记录下当前的结点是否在队列当中。
  4. 突然之间,我们发现,这就是我们接触过的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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值