洛谷4011 【网络流24题】孤岛营救问题(emmm,BFS?)

版权声明:欢迎转载!请注明出处!qwq https://blog.csdn.net/g21glf/article/details/86604944

传送门

【题目分析】

说是网络流24题但没看出哪里要用网络流。。。qwq也许我太菜了。

其实10*10的数据范围很容易想到暴力,但暴力可能会因为钥匙的存在而咕咕。

所以就考虑优化暴力。

发现钥匙种类不超过10种,所以考虑状压保存当前钥匙状态,0代表有,1代表没有。

然后就是一个坑点:一个地方可能有多把钥匙。。。

所以不能直接赋值而是同样用二进制表示当前位置的钥匙。

对于每一步,记录他的位置,用的步数和持有钥匙的情况,建一个优先队列,以步数为关键字。

然后就进行BFS,每走一步需要判断一下能不能走(两个点之间是否为墙,是否有当前门的钥匙)

因为用的是BFS,所以第一次走到终点即为最小步数,直接输出即可(结果我忘了还有-1这玩意儿qwq)

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=11;
const int MAXM=101;
const int INF=0x3f3f3f3f;

int n,m,p,k,s;
int flag=1;
int ma[MAXM][MAXM],key[MAXN][MAXN];
int dp[MAXN][MAXN][1<<MAXN];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
struct State{
	int step;
	int x,y;
	int keys;
	State(int a,int b,int c,int d){
		step=a;
		x=b,y=c;
		keys=d;
	}
	friend inline bool operator<(const State &a,const State &b){
		return a.step>b.step;
	}
};
priority_queue<State> q;

int Read(){
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

int id(int x,int y){
	return (x-1)*m+y;
}

int check(int state,int nx,int ny,int x,int y){
	int a=id(nx,ny),b=id(x,y);
	if(x<1||x>n||y<1||y>m)
	  return 0;
	if(ma[a][b]==-1)
	  return 1;
	else{
		int c=ma[a][b];
		if(state&(1<<(c-1)))
		  return 1;
		return 0;
	}
}

void bfs(){
	State s(0,1,1,0);
	q.push(s);
	memset(dp,INF,sizeof(dp));
	dp[1][1][0]=0;
	while(!q.empty()){
		State u=q.top();
		q.pop();
		if(u.x==n&&u.y==m){
			cout<<u.step;
			flag=0;
			return ;
		}
		int x=u.x,y=u.y,sta=u.keys;
		for(int i=0;i<4;++i){
			int nx=x+dx[i],ny=y+dy[i];
			if(check(u.keys,nx,ny,x,y)){
				if(key[nx][ny]!=-1){
					int c=key[nx][ny];
					int nxt=sta|c;
					if(dp[nx][ny][nxt]>dp[x][y][sta]+1){
						dp[nx][ny][nxt]=dp[x][y][sta]+1;
						State v(u.step+1,nx,ny,nxt);
						q.push(v);
					}
				}
				else{
					if(dp[nx][ny][sta]>dp[x][y][sta]+1){
						dp[nx][ny][sta]=dp[x][y][sta]+1;
						State v(u.step+1,nx,ny,sta);
						q.push(v);
					}
				}
			}
		}
	}
}

int main(){
	memset(ma,-1,sizeof(ma));
	memset(key,-1,sizeof(key));
	n=Read(),m=Read(),p=Read();
	k=Read();
	for(int i=1;i<=k;++i){
		int x=Read(),y=Read(),a=Read(),b=Read(),g=Read();
		int z=id(x,y),c=id(a,b);
		ma[z][c]=g,ma[c][z]=g;
	}
	s=Read();
	for(int i=1;i<=s;++i){
		int x=Read(),y=Read(),q=Read();
		if(key[x][y]==-1)
		  key[x][y]=0;
		key[x][y]|=(1<<(q-1));
	}
	bfs();
	if(flag)
	  puts("-1");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/86604944