HDU 3442 优先队列+BFS

141 篇文章 0 订阅
13 篇文章 0 订阅

点击打开链接

题意:刘备从起点走到终点,可以走的路块是'.'或者‘C'和起点和终点,然后给了A到E,代表了5种伤害,然后对于每种伤害只能对人造成伤害一次,解释一下样例应该就行了,刘备先向下走一次,受到A的一点伤害和B的两点伤害还有C的3点伤害,然后继续向下,虽然也在A和B的攻击范围,但是我已经受过它们的伤害所以不会再次受伤害,一样C已经对刘备造成过伤害,所以不再添加伤害,答案6

思路:挺简单的一道搜索题目,状态压缩学的不好,但是山人自有妙计,我开了7维的数组,每个伤害的状态只能是0或者1,走过便标记一下,剩下的就是简单的bfs了,然后就是找当前点可能收到的伤害,一共就5种,跑一遍找出来即可,我用vector把所有的伤害点全部记录下来找的,应该可以更简单一点,不多说了

#include <math.h>
#include <queue>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=60;
int sx,sy,ex,ey,n,m;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int vis[maxn][maxn][2][2][2][2][2];
char str[maxn][maxn];
struct edge1{
    int x,y;
    edge1(int a,int b){x=a;y=b;}
};
vector<edge1>G[10];
struct edge{
    int x,y,step,flag,flag1,flag2,flag3,flag4;
    friend bool operator< (edge n1,edge n2)
    {return n1.step>n2.step;}
};
bool judge(int id,int x,int y){
    int dis;
    if(id==1) dis=2;
    if(id==2) dis=3;
    if(id==3) dis=2;
    if(id==4) dis=1;
    for(unsigned int i=0;i<G[id].size();i++){
        edge1 e=G[id][i];
        if(abs(e.x-x)+abs(e.y-y)<=dis) return 1;
    }
    return 0;
}
int bfs(){
    priority_queue<edge>que;
    edge c,ne;
    memset(vis,0,sizeof(vis));
    str[sx][sy]='.';str[ex][ey]='.';
    c.x=sx,c.y=sy,c.step=0,c.flag=0,c.flag1=0,c.flag2=0,c.flag3=0,c.flag4=0;
    vis[c.x][c.y][0][0][0][0][0]=1;
    que.push(c);
    while(!que.empty()){
        c=que.top();que.pop();
        if(c.x==ex&&c.y==ey) return c.step;
        for(int i=0;i<4;i++){
            int xx=c.x+dir[i][0];
            int yy=c.y+dir[i][1];
            if(xx<0||xx>n-1||yy<0||yy>m-1||str[xx][yy]=='#') continue;
            if(str[xx][yy]!='.'&&str[xx][yy]!='C') continue;
            if(vis[xx][yy][c.flag][c.flag1][c.flag2][c.flag3][c.flag4]) continue;
            ne.x=xx;ne.y=yy;ne.step=c.step;ne.flag=c.flag;ne.flag1=c.flag1;ne.flag2=c.flag2;ne.flag3=c.flag3;ne.flag4=c.flag4;
            if(str[xx][yy]=='C'){
                if(ne.flag2==0){ne.flag2=1;ne.step+=3;}
            }
            if(ne.flag==0&&judge(1,xx,yy)){ne.flag=1;ne.step+=1;}
            if(ne.flag1==0&&judge(2,xx,yy)){ne.flag1=1;ne.step+=2;}
            if(ne.flag3==0&&judge(3,xx,yy)){ne.flag3=1;ne.step+=4;}
            if(ne.flag4==0&&judge(4,xx,yy)){ne.flag4=1;ne.step+=5;}
            vis[ne.x][ne.y][ne.flag][ne.flag1][ne.flag2][ne.flag3][ne.flag4]=1;
            que.push(ne);
        }
    }
    return -1;
}
int main(){
    int T,cas=1;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<10;i++) G[i].clear();
        for(int i=0;i<n;i++) scanf("%s",str[i]);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(str[i][j]=='$')sx=i,sy=j;
                if(str[i][j]=='!')ex=i,ey=j;
                if(str[i][j]=='A') G[1].push_back(edge1(i,j));
                if(str[i][j]=='B') G[2].push_back(edge1(i,j));
                if(str[i][j]=='D') G[3].push_back(edge1(i,j));
                if(str[i][j]=='E') G[4].push_back(edge1(i,j));
            }
        }
        int ans=bfs();
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值