acwing 3385. 玛雅人的密码

题目传送门

题目描述

玛雅人有一种密码,如果字符串中出现连续的 2012 四个数字就能解开密码。

给定一个长度为 N 的字符串,该字符串中只含有 0,1,2 三种数字。

可以对该字符串进行移位操作,每次操作可选取相邻的两个数字交换彼此位置。

请问这个字符串要移位几次才能解开密码。

例如 02120 经过一次移位,可以得到 20120,01220,02210,02102,其中 20120 符合要求,因此输出为 11。

如果无论移位多少次都解不开密码,输出 −1。

输入格式

第一行包含一个整数 NN,表示字符串的长度。

第二行包含一个由 0,1,2 组成的,长度为 NN 的字符串。

输出格式

若可以解出密码,则输出最少的移位次数;否则输出 −1。

数据范围

2≤N≤13

输入样例:

5
02120

输出样例:

1

bfs

分析

这个题一样

代码

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

bool is_have(string a, string b)
{
	for(int i = 0; i < a.size(); i++)
	{
		int k = i;
		int j = 0;
		while( k < a.size() && j < b.size() && a[k] == b[j] )
		{
			k++;
			j++;
		}
		if(j == b.size()) return true;
	}
	return false;
}

int bfs(string start)
{
	unordered_map<string, int> d; // 表示到某个状态的距离
	d[start] = 0;
	
	// bfs 常规操作 
	queue<string> q;
	q.push(start);
	
	while(q.size())
	{
		string t = q.front();
		q.pop();
		int dis = d[t];
		
		if(t.find("2012") != -1) return d[t];
//		if(is_have(t, "2012")) return d[t];
		
		string next;
		for(int i = 0; i < t.size() - 1; i++)
		{
			swap(t[i], t[i+1]);
			if(!d.count(t))
			{
				d[t] = dis + 1;
				q.push(t);
			}
			swap(t[i], t[i+1]);
		}	
	}
	return -1; 
}
 
 
int main()
{
	int n;
	string start;
	cin >> n;
	cin >> start;
	
	cout << bfs(start) << endl;
	
	return 0;
}

时间复杂度

参考文章

posted @ 2022-03-12 09:45  VanHope  阅读(56)  评论(0编辑  收藏  举报