玛雅人的密码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
using namespace std;
 
typedef long long LL;
const int N=1e5+10,mod=1e6;
const int MAX = 1e8 + 10 ;

/*思路就是bfs访问所有可能性,用set排除已经访问过的,最后输出step*/
/*这道题写了很久,最后原因是因为 swap 函数没有用引用,最后把返回类型void改成string返回
就对了。。这个错的太傻了
*/

//初始判断是否含有2 0 1 三个数字,没有的话直接输出-1 ; 

/*map 的插入方式用 数组的方式插入;
 vis.insert(pair<string , int >(str , size));  
 vis.insert(map<string, int>::value_type (str, size));  
 vis[str] = size++ ;  
*/
bool depend(int n , string a){
	bool exit_1 = false ;
	bool exit_0 = false ;
	bool exit_2 = false ;
	for(int i = 0 ; i < n ; i ++){
		if(a[i] == '0') exit_0 = true ;
		if(a[i] == '1') exit_1 = true ;
		if(a[i] == '2') exit_2 = true ;
	}
	if(exit_1 && exit_2 && exit_0){
		return true ;
	}
	return false ;
}

//节点保存字符串和 实现这个字符串的步骤 
struct node{
	string strcmp ; //字符串
	int step ; //得到字符串的步数
	
	node(){
		strcmp = "" ;
		step = 0 ;
	}
};

//输入的量 
int n ; //输入n ,这道题的这个 n 有点莫名其妙
string s ; //输入的字符串

queue <node> que ; //队列实现bfs   
set <string> vis2;// 来实现访问记录
/*其实用map<stirng, int>也可以不过,map还要多一个int的值显得有点多余,
因为这道题只要str就可以区别了*/

//交换函数 
string swap(string s , int n , int m){
	char c ;
	c = s[n] ;
	s[n] = s[m] ;
	s[m] = c ;
	return s;
}

/*string 的 find 函数真的好用
set里面找到str 的方式有很多,find(返回迭代器位置) , count(有几个)
clear() 清除set;
*/
int bfs(int  n ,string s){
	if(depend(n,s) == false ) return -1 ;
	
    //判断原来字符串中是否有2012,有直接返回 0 ; 
	
	if(s.find("2012") != -1){
		return 0 ;
	} 
	
	//没有2012  , 初始节点放入 
	node first ;
	first.strcmp = s;
	first.step = 0 ;
	que.push(first) ;
	vis[s] = size++ ;
	
	while( ! que.empty()){
		
		
		node tmp = que.front() ;
		que.pop() ;
		
		if(tmp.strcmp.find("2012") != -1){
			
			return tmp.step ;
		}
		
		for(int i = 0 ; i < tmp.strcmp.length()-1 ; i++){
			
			
			string str = tmp.strcmp ;
			str = swap(str , i , i+1) ;
			
			
			if(vis2.count(str) == 0 ) {//检查是不是旧的字符串 
			   //放入新的节点
				node new_node ;
				new_node.strcmp = str  ;
				new_node.step = tmp.step + 1 ;
				que.push(new_node) ;
				vis2.insert(str) ; 
			}
		}
	}
	return -1 ;
}
int main(){
	while(cin >> n >> s){
                //初始状态设置
		while(que.empty() == false ) que.pop() ;
		size = 0 ;
		vis2.clear() ;
		
		cout << bfs(n,s) <<endl;
	} 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值