hdu 1885 Key Task

迷宫游戏求解算法
本文介绍了一种解决迷宫游戏问题的算法实现,通过状态压缩的广度优先搜索(BFS)方法来寻找最短路径。该算法适用于迷宫中存在不同颜色的门和钥匙的情况,能够处理多个终点或无终点的情况。

怕是寒假做不完搜索1了......

题目:

The Czech Technical University is rather old — you already know that it celebrates 300 years of its existence in 2007. Some of the university buildings are old as well. And the navigation in old buildings can sometimes be a little bit tricky, because of strange long corridors that fork and join at absolutely unexpected places. 

The result is that some first-graders have often di?culties finding the right way to their classes. Therefore, the Student Union has developed a computer game to help the students to practice their orientation skills. The goal of the game is to find the way out of a labyrinth. Your task is to write a verification software that solves this game. 

The labyrinth is a 2-dimensional grid of squares, each square is either free or filled with a wall. Some of the free squares may contain doors or keys. There are four di?erent types of keys and doors: blue, yellow, red, and green. Each key can open only doors of the same color. 

You can move between adjacent free squares vertically or horizontally, diagonal movement is not allowed. You may not go across walls and you cannot leave the labyrinth area. If a square contains a door, you may go there only if you have stepped on a square with an appropriate key before.
InputThe input consists of several maps. Each map begins with a line containing two integer numbers R and C (1 ≤ R, C ≤ 100) specifying the map size. Then there are R lines each containing C characters. Each character is one of the following: 



Note that it is allowed to have 
more than one exit,
no exit at all,
more doors and/or keys of the same color, and
keys without corresponding doors and vice versa.

You may assume that the marker of your position (“*”) will appear exactly once in every map. 

There is one blank line after each map. The input is terminated by two zeros in place of the map size.OutputFor each map, print one line containing the sentence “Escape possible in S steps.”, where S is the smallest possible number of step to reach any of the exits. If no exit can be reached, output the string “The poor student is trapped!” instead. 

One step is defined as a movement between two adjacent cells. Grabbing a key or unlocking a door does not count as a step.Sample Input
1 10
*........X

1 3
*#X

3 20
####################
#XY.gBr.*.Rb.G.GG.y#
####################

0 0
Sample Output
Escape possible in 9 steps.
The poor student is trapped!
Escape possible in 45 steps.


题目大意:走迷宫,#是墙,*是起点,X是终点,. 是路,小写字母是钥匙,大写字母是门,可能没有终点,输出有终点时去最近的终点的路程。

解题思路:这道题跟前面那个基本一样,就是状态压缩bfs,区别就两点,一是终点(出口)不唯一,且可能不存在,在输入时要判断是否存在出口,不存在就不要bfs了;二是钥匙不是从a开始的。Y是第25个字母,但显然不能用2的25次方的储存状态,在输入时简单处理即可。

代码如下:

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int n,m,k;
char map[105][105];
int vis[105][105][1<<5];
struct node
{
    int x,y,step;
    int k;//记录状态
    node(int X=0,int Y=0,int Step=0,int K = 0)
    {
        x = X;
        y = Y;
        step = Step;
        k = K;
    }
}p,S,pp;

queue<node> que;

void pick_Up()
{
	int num = map[pp.x][pp.y] - 'a';
	pp.k |= (1 << num);
}

bool cannot_Open(int num)
{
	int a = p.k#
	return a==0;//检验有没有相应的钥匙 
}

int bfs()
{
	que.push(S);
	int num;
	vis[S.x][S.y][0] = 1;
	while(!que.empty())
	{

		p = que.front();
		que.pop();
		if(map[p.x][p.y]=='X')
			return p.step; 
		for(int i=0;i<4;i++)
		{		
			pp.x = p.x+dx[i];
			pp.y = p.y+dy[i];
			pp.step = p.step+1;
			pp.k = p.k;
			if(!map[pp.x][pp.y]||map[pp.x][pp.y]=='#')//判断边界    
				continue;    
			if(map[pp.x][pp.y]=='B'||map[pp.x][pp.y]=='A'||map[pp.x][pp.y]=='C'||map[pp.x][pp.y]=='D')//遇到门 
			{				
				num =  map[pp.x][pp.y] - 'A';//A门对应0,B门对应1...... 
				num = 1<<num;//转换为2进制的位,如有A门对应pow(2,0)(第一位上的1),B门对应pow(2,1)(第二位上的1)...... 
				if(cannot_Open(num))
					continue;					
			}
			else if(map[pp.x][pp.y]=='b'||map[pp.x][pp.y]=='a'||map[pp.x][pp.y]=='c'||map[pp.x][pp.y]=='d')//钥匙 
			{
				pick_Up();//遇到钥匙就捡起来...  

			}
			
			if(!vis[pp.x][pp.y][pp.k])//同一状态同一地点只走一次 
			{
				vis[pp.x][pp.y][pp.k] = 1;
				que.push(pp);
			}		
		}
	}
	return -1;
}

void init() 
{
	memset(map,0,sizeof(map));
	memset(vis,0,sizeof(vis));
	while(!que.empty())
	{
		que.pop();	
	}	
}

int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n>>m&&(n||m))
    {
    	k = 0; 
    	init();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>map[i][j];
                if(map[i][j]=='R'||map[i][j]=='r')//一开始忘记处理,遇到Y就崩了。。。 
                	map[i][j] -= ('R' - 'A');
                else if(map[i][j]=='G'||map[i][j]=='g')
                	map[i][j] -= ('G' - 'C');
                else if(map[i][j]=='G'||map[i][j]=='g')
                	map[i][j] -= ('G' - 'C');
                else if(map[i][j]=='Y'||map[i][j]=='y')
                	map[i][j] -= ('Y' - 'D');
                if(map[i][j]=='X')
                {
                	k = 1;
				}
				else if(map[i][j]=='*')
				{
					S.x = i;
					S.y = j;
				}
            }
        }
        if(k==0)
        {
        	cout<<"The poor student is trapped!"<<endl;
        	continue;
		}	
       	int ans = bfs();
       	if(ans==-1)
       	{
       		cout<<"The poor student is trapped!"<<endl;
        	continue;	
		}
		cout<<"Escape possible in "<<ans<<" steps.\n";
       		
    }
}

【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器状态空间平均模型的建模策略。该方法通过对系统中多个相互耦合的DC-DC变换器进行统一建模,构建出整个微电网的集中状态空间模型,并在此基础上实施线性化处理,便于后续的小信号分析与稳定性研究。文中详细阐述了建模过程中的关键步骤,包括电路拓扑分析、状态变量选取、平均化处理以及雅可比矩阵的推导,最终通过Matlab代码实现模型仿真验证,展示了该方法在动态响应分析和控制器设计中的有效性。; 适合人群:具备电力电子、自动控制理论基础,熟悉Matlab/Simulink仿真工具,从事微电网、新能源系统建模与控制研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网中多变换器系统的统一建模方法;②理解状态空间平均法在非线性电力电子系统中的应用;③实现系统线性化并用于稳定性分析与控制器设计;④通过Matlab代码复现和扩展模型,服务于科研仿真与教学实践。; 阅读建议:建议读者结合Matlab代码逐步理解建模流程,重点关注状态变量的选择与平均化处理的数学推导,同时可尝试修改系统参数或拓扑结构以加深对模型通用性和适应性的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值