[BFS+位运算+状态压缩]位运算的真谛(赋c++和java代码)

原题链接

Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……

这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。

Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:

. 代表路

  • 代表墙
    @ 代表Ignatius的起始位置
    ^ 代表地牢的出口
    A-J 代表带锁的门,对应的钥匙分别为a-j
    a-j 代表钥匙,对应的门分别为A-J

每组测试数据之间有一个空行。

Output
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。

Sample Input
4 5 17
@A.B.
a*..
^
c…b

4 5 16
@A.B.
a*..
^
c…b

Sample Output
16
-1

这才理解位运算


/*
	题目一共有10把钥匙,用二进制的1<<10代表每把钥匙的状态,比如:
	1000000000 这个二进制的数字表示只拿到了第一把钥匙
	每碰到一扇门,就用当前手中钥匙的状态按位与一下这个门的位置,
	按位与出的结果是0,就代表有这把钥匙,否则没有 
	比如:现在手里的10把钥匙的状态是1000000000代表我只拿到了最高位的钥匙
	也就是钥匙J
	现在的门也是J 那么门的二进制表示就是 1000000000 他们按位与以后得到的
	结果是1表示可以开门
	
	每次碰到门就按位与判断,每次碰到钥匙就按位或更新当前手中钥匙的状态


*/

#include<bits/stdc++.h>
using namespace std;

int n,m,t;
char mapp[25][25];
int sx,sy,ex,ey;
int dir[4][2]={-1,0,1,0,0,-1,0,1};

struct node{
	int x,y;
	int step;
	int key;
};

int vis[25][25][(1<<10)+10];

bool check(int x,int y)
{
	if(x<1||x>n||y<1||y>m||mapp[x][y]=='*'){
		return false;
	}
	return true;
}

int bfs()
{
	queue<node> q;
	memset(vis,0,sizeof vis);
	node first;
	first.x=sx;
	first.y=sy;
	first.step=0;
	first.key=0;
	q.push(first);
	node next;
	while(q.size()){
		node fr=q.front();
		//cout<<fr.x<<endl;
		q.pop();
		if(fr.x==ex&&fr.y==ey){
			return fr.step;
		}
		for(int i=0;i<4;i++){
			next.x=fr.x+dir[i][0];
			next.y=fr.y+dir[i][1];
			next.key=fr.key;
			next.step=fr.step;
			if(!check(next.x,next.y)||vis[next.x][next.y][next.key]){
				continue;
			}
			next.step++;
			if(next.step>=t){
				continue;
			}
			if(mapp[next.x][next.y]>='A'&&mapp[next.x][next.y]<='J'){
				int tmp=mapp[next.x][next.y]-'A';
				int flag=(next.key&(1<<tmp));
				if(flag){
					vis[next.x][next.y][next.key]=1;
					q.push(next);
				}
			}
			else if(mapp[next.x][next.y]>='a'&&mapp[next.x][next.y]<='j'){
				int tmp=mapp[next.x][next.y]-'a';
				next.key=(fr.key|(1<<tmp));
				vis[next.x][next.y][next.key]=1;
				q.push(next);
			}
			else{
				//if(!vis[next.x][next.y][next.key]){
					vis[next.x][next.y][next.key]=1;
					q.push(next);
				//}
			}
		}
	}
	return -1;
}

int main()
{
	while(cin>>n>>m>>t){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>mapp[i][j];
				if(mapp[i][j]=='@'){
					sx=i;
					sy=j;			
				}
				else if(mapp[i][j]=='^'){
					ex=i;
					ey=j;
				}
			} 
		}
		cout<<bfs()<<endl;
	}


	return 0;
}

下面是java代码 。。刚开始用java写题解

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;

import static java.lang.Integer.min;
import static java.lang.Math.*;

public class Main {
    private static int n,m,t,sx,sy,ex,ey;
    private static char[][] map=new char[25][25];
    private static int[] dirx={-1,0,0,1};
    private static int[] diry={0,1,-1,0};

    public static void main(String[] args) throws Exception {
        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNext()){
            n=scanner.nextInt();
            m=scanner.nextInt();
            t=scanner.nextInt();
            String str=null;
            for (int i = 1; i <= n; i++) {
                str=scanner.next();
                //System.out.println(str.length());
                for (int j = 0; j < str.length(); j++) {
                    map[i][j+1]=str.charAt(j);
                    if(str.charAt(j)=='@'){
                        sx=i;
                        sy=j+1;
                    }else if (str.charAt(j)=='^'){
                        ex=i;
                        ey=j+1;
                    }
                }
            }

            System.out.println(bfs());

        }
        scanner.close();
    }

    public static int bfs(){
        int[][][] vis=new int[25][25][1<<10+2];
        class node{
            private int x;
            private int y;
            private int step;
            private int key;

            public node(int x, int y, int step, int key) {
                this.x = x;
                this.y = y;
                this.step = step;
                this.key = key;
            }

            public int getX() {
                return x;
            }

            public void setX(int x) {
                this.x = x;
            }

            public int getY() {
                return y;
            }

            public void setY(int y) {
                this.y = y;
            }

            public int getStep() {
                return step;
            }

            public void setStep(int step) {
                this.step = step;
            }

            public int getKey() {
                return key;
            }

            public void setKey(int key) {
                this.key = key;
            }
        }
        Queue<node> q=new LinkedList<>();
        q.offer(new node(sx,sy,0,0));
        //
        while(q.size()!=0){
            node fr = new node(q.element().getX(),q.element().getY(),q.element().getStep(),q.element().getKey());
            //System.out.println(q.element().getX()+"   "+q.element().getY());
            q.poll();
            if (fr.getX()==ex&&fr.getY()==ey){
                return fr.getStep();
            }
            for (int i = 0; i < 4; i++) {
                node next = new node(fr.getX()+dirx[i],fr.getY()+diry[i],fr.getStep()+1,fr.getKey());
                if (next.getX()<1||next.getX()>n||next.getY()<1||next.getY()>m||map[next.getX()][next.getY()]=='*'||vis[next.getX()][next.getY()][next.getKey()]==1){
                    continue;
                }
                if (next.getStep()>=t){
                    continue;
                }
                if(map[next.getX()][next.getY()]>='A'&&map[next.getX()][next.getY()]<='J'){
                    int tmp=map[next.getX()][next.getY()]-'A';
                    int flag = (next.getKey()&(1<<tmp));
                    if (flag!=0){
                        //next.setStep(fr.getStep()+1);
                        vis[next.getX()][next.getY()][next.getKey()]=1;
                        //System.out.println(next.getX()+"-->"+next.getY()+"    AJ");
                        q.offer(new node(next.getX(),next.getY(),next.getStep(),next.getKey()));
                    }
                }
                else if(map[next.getX()][next.getY()]>='a'&&map[next.getX()][next.getY()]<='j'){
                    int tmp=map[next.getX()][next.getY()]-'a';
                    //int ans=(fr.getKey()|(1<<tmp));
                    next.setKey(fr.getKey()|(1<<tmp));
                    vis[next.getX()][next.getY()][next.getKey()]=1;
                    //next.setStep(fr.getStep()+1);
                    //System.out.println(next.getX()+"-->"+next.getY()+"    aj");
                    q.offer(new node(next.getX(),next.getY(),next.getStep(),next.getKey()));
                }
                else{
                    vis[next.getX()][next.getY()][next.getKey()]=1;
                    //System.out.println(next.getX()+"-->"+next.getY()+"    space");
                    q.offer(new node(next.getX(),next.getY(),next.getStep(),next.getKey()));
                }
            }
        }
        return -1;
    }



}

猜你喜欢

转载自blog.csdn.net/qq_44833767/article/details/105509024