• [网络流24题]孤岛营救问题


    分析

    网络流24题总结

    这题直接状压BFS也可以,不过可以把BFS改成SPFA,进一步优化

    显然要维护三个状态:s,x,y,分别表示钥匙状态s(用一个二进制表示,第i位为1表示当前有第i个钥匙),和当前的x,y坐标,以这三个状态来分层

    那么设dist(s,x,y)表示到达当前状态的最短时间

    转移就跟BFS的转移一样,除了判断条件里要加关于dist的判断,详见代码

    代码

    最短路:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<bitset>
    #define maxn 15
    #define INF 0x3f3f3f3f
    using namespace std;
    struct node{
    	int x;
    	int y;
    	int k;
    	node(){
    		
    	}
    	node(int xx,int yy,int key){
    		x=xx;
    		y=yy;
    		k=key;
    	}
    };
    int n,m,p,k,s; 
    int dist[2505][maxn][maxn];
    int inq[2505][maxn][maxn];
    int key[maxn][maxn];
    int door[maxn][maxn][maxn][maxn];
    const int walkx[4]={1,-1,0,0};
    const int walky[4]={0,0,1,-1};
    int spfa(){
    	queue<node>q;
    	q.push(node(1,1,key[1][1]));
    	inq[key[1][1]][1][1]=1;
    	memset(dist,0x3f,sizeof(dist)); 
    	dist[key[1][1]][1][1]=0;
    	while(!q.empty()){
    		node now=q.front();
    		q.pop();
    		inq[now.k][now.x][now.y]=0;
    		for(int i=0;i<4;i++){
    			int x=now.x+walkx[i];
    			int y=now.y+walky[i];
    			if(x>=1&&x<=n&&y>=1&&y<=m){ 
    				if((door[now.x][now.y][x][y]>=1 && (now.k & (1<<door[now.x][now.y][x][y])) !=0)||door[now.x][now.y][x][y]==-1){
    					if(dist[now.k|key[x][y]][x][y]>dist[now.k][now.x][now.y]+1){
    						dist[now.k|key[x][y]][x][y]=dist[now.k][now.x][now.y]+1;
    						if(!inq[now.k|key[x][y]][x][y]){
    							inq[now.k|key[x][y]][x][y]=1;
    							q.push(node(x,y,now.k|key[x][y]));
    						} 
    					} 
    				}
    			} 
    		}
    	}
    	int ans=INF;
    	for(int i=0;i<(1<<(p+1));i++){
    		ans=min(ans,dist[i][n][m]);
    	}
    	if(ans==INF) return -1;
    	else return ans;
    }
    
    int main(){
    	int x1,y1,x2,y2,g;
    	scanf("%d %d %d",&n,&m,&p);
    	scanf("%d",&k);
    	memset(door,0xff,sizeof(door));
    	for(int i=1;i<=k;i++){
    		scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&g);
    		door[x1][y1][x2][y2]=g;	
    		door[x2][y2][x1][y1]=g;
    	}
    	scanf("%d",&s);
    	for(int i=1;i<=s;i++){
    		scanf("%d %d %d",&x1,&y1,&g);
    		key[x1][y1]|=(1<<g);
    	}
    	printf("%d
    ",spfa());
    } 
    

    状压BFS:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<bitset>
    #define maxn 15
    using namespace std;
    struct node{
    	int x;
    	int y;
    	int k;
    	int t;
    	node(){
    		
    	}
    	node(int xx,int yy,int key,int tim){
    		x=xx;
    		y=yy;
    		k=key;
    		t=tim;
    	}
    	void debug(){
    		printf("(%d,%d) tim=%d ",x,y,t);
    		cout <<"key="<<bitset<10>(k)<<endl;
    	}
    };
    int n,m,p,k,s; 
    int vis[2005][maxn][maxn];
    int key[maxn][maxn];
    int door[maxn][maxn][maxn][maxn];
    const int walkx[4]={1,-1,0,0};
    const int walky[4]={0,0,1,-1};
    int bfs(){
    	queue<node>q;
    	q.push(node(1,1,key[1][1],0));
    	vis[key[1][1]][1][1]=1;
    	while(!q.empty()){
    		node now=q.front();
    		q.pop();
    //		now.debug();
    		if(now.x==n&&now.y==m){
    			return now.t;
    		} 
    		for(int i=0;i<4;i++){
    			int x=now.x+walkx[i];
    			int y=now.y+walky[i];
    			if(x>=1&&x<=n&&y>=1&&y<=m){ 
    				if(door[now.x][now.y][x][y]==0) continue;
    				if((door[now.x][now.y][x][y]>=1 && (now.k & (1<<door[now.x][now.y][x][y])) !=0)||door[now.x][now.y][x][y]==-1){
    					if(vis[now.k|key[x][y]][x][y]) continue;
    					vis[now.k|key[x][y]][x][y]=1;
    					q.push(node(x,y,now.k|key[x][y],now.t+1)); 
    				}
    			} 
    		}
    	}
    	return -1;
    }
    
    int main(){
    	int x1,y1,x2,y2,g;
    	scanf("%d %d %d",&n,&m,&p);
    	scanf("%d",&k);
    	memset(door,0xff,sizeof(door));
    	for(int i=1;i<=k;i++){
    		scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&g);
    		door[x1][y1][x2][y2]=g;	
    		door[x2][y2][x1][y1]=g;
    	}
    	scanf("%d",&s);
    	for(int i=1;i<=s;i++){
    		scanf("%d %d %d",&x1,&y1,&g);
    		key[x1][y1]|=(1<<g);
    	}
    	printf("%d
    ",bfs());
    } 
    
  • 相关阅读:
    自制操作系统Antz(11)——实现shell(下)命令响应
    自制操作系统Antz(10)——实现shell(上)
    利用Android-FingerprintManager类实现指纹识别
    C语言解析WAV音频文件
    自制病毒——控制桌面鼠标以及开关机
    Linux内核源码分析 day01——内存寻址
    后端必备的Linux知识
    Java基础面试题总结
    自制操作系统Antz(9)——实现内核 (下) 实现图形化界面
    自制操作系统Antz(8)——实现内核 (中) 扩展内核
  • 原文地址:https://www.cnblogs.com/birchtree/p/10602837.html
Copyright © 2020-2023  润新知