2020.01.15【NOIP提高组】模拟B组——T3分球

题目描述

在一个装满财宝的屋子里,有2N个盒子排成一排。除了两个相邻的空盒外,其余的每个盒子里都装有一个金球或者一个银球,总共有N-1个金球和N-1个银球。以下是一个N=5时的例子,G表示金球,S表示银球:

任意两个相邻的非空的盒子里的球可以移动到两个相邻的空盒中,移动不能改变这两个球的排列顺序。写一个程序,用最少的移动次数把所有的金球都移到所有银球的左边。

输入格式

输入文件包含多组数据。第一行为K,表示数据的总数。

每组数据的第一行是N(3<=N<=7),第二行是2N个盒子的初始状态。金球用a表示,银球用b表示,空盒用空格表示。每两组相邻数据用空行隔开。

输出格式

对于每一组数据,若无解则输出一行-1,若有解,输出最少移动次数,相邻的两组数据用一个空行隔开。

样例输入

3
3
abab
5
abba abab
6
a babbababa

样例输出

-1
3
4

解题思路

此题n<=7,显然爆搜是ok的,但是问题就是一个状态如何标记了,题目给的是字符串,一般的方法肯定是不行的,大家可以考虑哈希。但这里推出一种更神奇的方法:(仅限c++)

map!!!

map为c++stl库的一个关联函数,可以实现快速查找,复杂度为O(logn)

map实现从键到值的映射,其效率高因为它用平衡二叉树来储存与访问 。(不用看了,反正我看不懂。)

总之呢,这个东西就可以让(bool)b[“abababab”]=1成为现实,十分好用。

那就很easy了。

代码来!!!

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>//头文件
using namespace std;
string s,s1,s2;
string f[20007];//队列的状态
int t,n,d[20007];//步数
bool bz1,bz2;
string read(){//快读
	string a;char ch=getchar();
	while(ch!='a'&&ch!='b'&&ch!=' ')ch=getchar();
	while(ch=='a'||ch=='b'||ch==' '){a+=ch;ch=getchar();}
	return a;
}
void bfs(){
	int h=0,t=1,tot;
	map<string,bool>b;//定义
	b[s]=1;
	f[t]=s;
	d[t]=0;
	while(h<t){
		s1=f[++h];
		bz1=bz2=true;
		for(int j=0;j<s1.length();j++){
			if(s1[j]=='b')bz1=false;
			if(!bz1&&s1[j]=='a'){bz2=false;break;}
		}
		if(bz2){printf("%d\n",d[h]);return;}
		//这一段查看是否符合了题意(金在银左边)
		for(int i=1;i<s1.length();i++){
		//搜索下一个状态,这里设i,i-1为移动的两个盒子的位置
			if(s1[i]==' '||s1[i-1]==' ')continue;//为空就换下一个
			s2="";//s2为更新后的状态
			tot=0;
			for(int j=0;j<=i-2;j++) 
				if(s1[j]!=' ')s2+=s1[j];
				else {
					if(tot==0)s2+=s1[i-1],tot++;
					else s2+=s1[i];
				}
			s2+="  ";
			tot=0;
			for(int j=i+1;j<s1.length();j++)
				if(s1[j]!=' ')s2+=s1[j];
				else {
					if(tot==0)s2+=s1[i-1],tot++;
					else s2+=s1[i];
				}
			//上面为求s2的过程,若有大佬会用函数更快那小弟也只能膜拜
			if(b[s2])continue;//判断有没有出现过
			b[s2]=1;
			t++;
			f[t]=s2;
			d[t]=d[h]+1;
			//入队过程
		}
	}
	printf("-1\n");//不可能达到
	return;
}

int main(){
	scanf("%d",&t);
	while(t!=0){
		t--;
		scanf("%d",&n);
		s=read();//读入
		bfs();//宽搜
	}
}

同样使用map的一道例题的网址:c++STL库map的运用——昵称

END!!!

THANK YOU!!!

发布了16 篇原创文章 · 获赞 2 · 访问量 1531

猜你喜欢

转载自blog.csdn.net/jay_zai/article/details/103994672