Three Kingdoms(BFS状压)(HDU3442)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3442

题目大意:就是有ABCDE五种塔,(其实不是塔,但是还是可以把它们看成塔),然后每种塔有特定的攻击范围和攻击力,其中,只有C可以走,其他的塔不能走。我们要从起点走到终点,看是否能走到,能走到就要找最小的伤害值。
另外就是每种塔的攻击只能有一次。

题解:我们先将每个点的伤害预处理一下,然后就开始bfs,bfs我们采取的是得到到达终点的最小伤害值,如果不能到达终点就直接return-1。其实是可以不用优先队列的,因为我们是要得到所有能够到达终点的路径的伤害的最小值,我们有ans每次比较存储,所以不需要按照伤害值的大小在队列中排序,因为队列是要清空的最后。所以呢,可以直接用队列来做,没有什么区别的实际上。

需要注意的就是,这里说到了一个曼哈顿距离,影响到了塔的攻范围,所以百度一下曼哈顿距离是什么然后再做。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;

int n,m;
char mp[55][55];
bool vis[55][55][50];
int sx,sy;
int dam[55][55];
const int dir[4][2]={
        0,1,
        1,0,
        -1,0,
        0,-1
};
const int hurt[5]={1,2,3,4,5};
const int range[5]={2,3,0,2,1};
struct node{
    int x,y,state,hp;
    node(int a=0,int b=0,int c=0,int d=0):x(a),y(b),state(c),hp(d){}
    friend bool operator < (node n1,node n2)
    {
        return n1.hp>n2.hp;
    }
};

bool InMap(int x,int y)
{
    return x>=1&&x<=n&&y>=1&&y<=m;
}
bool IsTower(int x,int y)
{
    return mp[x][y]=='A'||mp[x][y]=='B'||mp[x][y]=='D'||mp[x][y]=='E';
}
void f()
{
    memset(dam,0,sizeof(dam));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int ttx,tty;
            if(mp[i][j]>='A'&&mp[i][j]<='E')
            {
                int id=mp[i][j]-'A';
                for(int ii=0;ii<=range[id];ii++)
                {
                    for(int jj=range[id]-ii;jj>=0;jj--)
                    {
                        ttx=i+ii;
                        tty=j+jj;
                        if(InMap(ttx,tty))
                            dam[ttx][tty]|=(1<<id);
                        ttx=i-ii;
                        tty=j+jj;
                        if(InMap(ttx,tty))
                            dam[ttx][tty]|=(1<<id);
                        ttx=i+ii;
                        tty=j-jj;
                        if(InMap(ttx,tty))
                            dam[ttx][tty]|=(1<<id);
                        ttx=i-ii;
                        tty=j-jj;
                        if(InMap(ttx,tty))
                            dam[ttx][tty]|=(1<<id);
                    }
                }
            }
        }
    }
}
int bfs()
{
    f();
    int ans=INF;
    int flag=0;
    memset(vis,false,sizeof(vis));
    priority_queue<node>q;
    q.push(node(sx,sy,0,0));
    vis[sx][sy][0]=true;
    while(!q.empty())
    {
        for(int i=0;i<4;i++)
        {
            int tx=q.top().x+dir[i][0];
            int ty=q.top().y+dir[i][1];
            if(mp[tx][ty]=='#'||!InMap(tx,ty)||IsTower(tx,ty))
                continue;
            if(mp[tx][ty]!='!'&&!(dam[tx][ty]^0))//如果没有伤害,就直接push
            {
                if(vis[tx][ty][q.top().state])
                    continue;
                q.push(node(tx,ty,q.top().state,q.top().hp));
                vis[tx][ty][q.top().state]=true;
            }
            else
            {
                int state=q.top().state,tmp_hp=q.top().hp;
                for(int j=0;j<=4;j++)
                {
                    if(((dam[tx][ty]>>j)&1)&&!(q.top().state>>j&1))//之前没有受到过这儿的伤害
                    {
                        state|=1<<j;
                        tmp_hp+=hurt[j];
                    }
                }
                if(vis[tx][ty][state])
                    continue;
                if(mp[tx][ty]=='!')//如果到了终点
                {
                    flag=1;
                    if (ans > tmp_hp)
                        ans = tmp_hp;
                    vis[tx][ty][state] = true;
                    continue;
                }
                q.push(node(tx,ty,state,tmp_hp));
                vis[tx][ty][state]=true;
            }
        }
        q.pop();
    }
    if(flag==0)
        return -1;
    else
        return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        scanf("%d%d",&n,&m);
        getchar();
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=m;k++)
            {
                scanf("%c",&mp[j][k]);
                if(mp[j][k]=='$')
                {
                    sx=j;
                    sy=k;
                    mp[j][k]='.';
                }
            }
            getchar();
        }
        printf("Case %d: %d\n",i,bfs());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/88372685
今日推荐