• NOIp模拟题 T3 密室逃脱


    题面

    即使 czhou 没有派出最强篮球阵容,机房篮球队还是暴虐了校篮球队。为了不打击校篮球队信心,czhou 决定改变训练后的活动。近来,江大掌门的徒弟徒孙们纷纷事业有成,回到母校为机房捐钱捐物。财大气粗的机房组收回了五层六层的所有教室。Czhou 决定将六层的教室改造为智能密室逃脱活动室。每天傍晚,神牛们可以依次逐个进入游玩。我们简单的将教室分割为 n*n 个房间,K 是你初始所在房间,T 是你最终逃脱的房间。如果你想要逃脱房间,你必须依次找到 m 把钥匙。我们假定你从一个房间进入另一个房间需要花费 1 的时间。当然某些房间有些特殊的问题(地图上 S 表示)需要回答才能通过,对于机智的众牛们来说,这些问题根本不是问题。我们假定众牛们花费 1 的时间解决问题。(主要是出题的人表述不清,导致众牛理解困难;当然
    问题只需要回答一次,下次再次进入房间不需要回答了)

    Input:maze.in
    第一行两个数字 n,m
    接下来 n*n 描述地图

    Output: maze.out
    需要最少时间逃脱密室。若无解输出 impossible

    Sample1.in:

    3 1
    K.S
    ##1
    1#T
    

    Sample1.out

    5
    

    Sample2.in

    3 1
    K#T
    .S#
    1#.
    

    Sample2.out

    impossible
    

    Sample3.in

    3 2
    K#T
    .S.
    21.
    

    Sample3.out

    8
    

    样例 3 说明:
    要先取钥匙 1,再取钥匙 2。地图上可能有多个同一种钥匙,#为墙壁即不可走.

    数据范围:(0 < N leq 100), (0 leq M leq 9) , (S)的个数不超过(5)

    思路

    看到迷宫加上最少步数果断bfs,但是难点在于走的时候难以记录某一个S是否走过。但是我们注意到S的个数很少,所以直接暴力枚举(2^5)看看每一个S有没有走过。如果走过那么就将这个S变成.,答案++;如果没走那么就把它变成#。这样对每一个选取S的方案进行bfs,得出最终的答案即可。总时间复杂度(O(n^2*m*2^5))

    Code

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int ans=2147483647;
    int n,m,tot,sx,lx,sy,ly;
    char a[110][110];
    int f[110][110][20];
    int qx[100010],qy[100010],qm[100010];
    int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
    int x[20],y[20];
    void bfs(){
    	memset(f,-1,sizeof(f));
    	qx[0]=sx;qy[0]=sy;
    	int head=0,tail=1;
    	f[sx][sy][0]=0;
    	while(head!=tail){
    		int x=qx[head],y=qy[head],t=qm[head];
    		head++;
    		for(int i=0;i<4;i++){
    			int nowx=x+xx[i],nowy=y+yy[i],nowm=t;
    			if(nowx<1||nowy<1||nowx>n||nowy>n) continue;
    			if(nowm+1==a[nowx][nowy]-'0') nowm++;
    			if(a[nowx][nowy]=='#'||f[nowx][nowy][nowm]!=-1) continue;
    			f[nowx][nowy][nowm]=f[x][y][t]+1;
    			qx[tail]=nowx;
    			qy[tail]=nowy;
    			qm[tail]=nowm;
    			tail++;
    		}
    	}
    }
    void dfs(int now,int k){
    	if(now==tot+1){
    		bfs();
    		if(f[lx][ly][m]!=-1){
    			ans=min(ans,k+f[lx][ly][m]);
    		}
    		return;
    	}
    	a[x[now]][y[now]]='.';
    	dfs(now+1,k+1);
    	a[x[now]][y[now]]='#';
    	dfs(now+1,k);
    }
    int main()
    {
    	freopen("maze.in","r",stdin);
    	freopen("maze.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			cin>>a[i][j];
    			if(a[i][j]=='K'){
    				sx=i;sy=j;
    			}
    			else if(a[i][j]=='T'){
    				lx=i;ly=j;
    			}
    			else if(a[i][j]=='S'){
    				tot++;
    				x[tot]=i;y[tot]=j;
    			}
    		}
    	}
    	dfs(1,0);
    	if(ans==2147483647){
    		printf("impossible
    ");
    	}
    	else{
    		printf("%d
    ",ans);	
    	}
    	return 0;
    }
    
  • 相关阅读:
    17 盒子模型
    16 input默认样式清除
    15 组合选择器
    14 CSS权重深入
    13 CSS样式权重问题
    12 子代选择器和后代选择器
    11 CSS的三种引入方式和基本选择器
    10 table标签
    NOIP1998拼数
    NOIP1998车站
  • 原文地址:https://www.cnblogs.com/57xmz/p/14416667.html
Copyright © 2020-2023  润新知