【BFS+优先队列】HDU 3442 Three Kingdoms

/* 
Three Kingdoms
时间: 2017/02/25 
题意:刘备逃跑,从'$'逃到'!',除了'.'和'C'能走其他不能走,走'C'处要受伤害,其他字母各有攻击范围和伤害值,
问刘备逃跑最少扣的血或不能逃到目的地
题解:全程搜索 
先BFS搜索每个有范围字母能触及到的位置存储起来。
再从起点BFS到终点,但是注意要使用优先队列优化这个BFS。。。
打的比较挫
*/  
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;
#define LL long long
#define N 105
#define INF 0x3f3f3f3f
const double esp = 1e-6;

struct node
{
    int x,y,vis,val;
    bool operator < ( const node& a )const
    {
        return val > a.val;
    }
};
struct point
{
    int x,y,s;
};
int dx[5] = {0,0,1,-1};
int dy[5] = {1,-1,0,0};
char ma[N][N];
bool vis[N][N];
int mp[N][N][10];
int n,m;
bool pan(int x,int y)
{
    if(x >= 0 && x < n && y >= 0 && y < m)
        return true;
    return false;
}
void BFS(int x, int y,int val,int step)
{
    queue<point> p;
    point now,next;
    now.x = x;
    now.y = y;
    now.s = 0;
    p.push(now);
    vis[x][y] = 1;
    while(!p.empty())
    {
        now = p.front();
        p.pop();
        mp[now.x][now.y][val] = 1;
        for(int i = 0; i < 4; i++)
        {
            next.x = dx[i]+now.x;
            next.y = dy[i]+now.y;
            next.s = now.s+1;
            if(pan(next.x,next.y) && vis[next.x][next.y] != 1 && next.s <= step)
            {
                p.push(next);
                vis[next.x][next.y] = 1;
            }
        }
    }
    return ;
}
int ans;
int _BFS(int x, int y)
{
    priority_queue<node> p;
    node now,next;
    now.x = x;
    now.y = y;
    now.vis = 0;
    now.val = 0;
    p.push(now);
    vis[x][y] = 1;
    while(!p.empty())
    {
        now = p.top();
        if(ma[now.x][now.y] == '!')
            return now.val;
        p.pop();
        for(int i = 0; i < 4; i++)
        {
            next.x = dx[i]+now.x;
            next.y = dy[i]+now.y;
            if(pan(next.x,next.y) && vis[next.x][next.y] != 1 && ma[next.x][next.y] != '#')
            {
                next.val = now.val;
                next.vis = now.vis;
                for(int j = 1; j <= 5; j++)
                {
                    if(mp[next.x][next.y][j] && !(now.vis & (1 << (j-1))))
                    {
                        next.val += j;
                        next.vis += (1<<(j-1));
                    }
                }
                p.push(next);
                vis[next.x][next.y] = 1;
            }
        }
    }
    return -1;
}
int main()
{
    int T,cas = 1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(ma,0,sizeof(ma));
        memset(mp,0,sizeof(mp));
        for(int i = 0; i < n; i++)
            scanf("%s",ma[i]);
        int bx,by;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(ma[i][j] == 'A')
                {
                    ma[i][j] = '#';
                    memset(vis,0,sizeof(vis));
                    BFS(i,j,1,2);
                }
                else if(ma[i][j] == 'B')
                {
                    ma[i][j] = '#';
                    memset(vis,0,sizeof(vis));
                    BFS(i,j,2,3);
                }
                else if(ma[i][j] == 'C')
                {
                    ma[i][j] = '.';
                    mp[i][j][3] = 1;
                }
                else if(ma[i][j] == 'D')
                {
                    ma[i][j] = '#';
                    memset(vis,0,sizeof(vis));
                    BFS(i,j,4,2);
                }
                else if(ma[i][j] == 'E')
                {
                    ma[i][j] = '#';
                    memset(vis,0,sizeof(vis));
                    BFS(i,j,5,1);
                }
                else if(ma[i][j] == '$')
                {
                    bx = i;
                    by = j;
                }
            }
        }
        memset(vis,0,sizeof(vis));
        ans = _BFS(bx,by);
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值