首页 > 试题广场 >

密码锁

[编程题]密码锁
  • 热度指数:3758 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串(2=<N<=13),该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。


输入描述:
第一行输入N,第二行输入N个数字,只包含0,1,2


输出描述:
输出字符串要移几位才能解开密码,如果无论移位多少次都解不开密码,输出-1
示例1

输入

5
02120
5
02120

输出

1
1
1.当不含有0,1,2,2四个字符时,不能解锁;
2.当含有上述四个字符,考虑DFS,BFS;因为这里需要输出移动次数(应该是最少),选择BFS
3.访问标记数组,使用map映射;
#include<iostream>
(720)#include<vector>
#include<string>
(765)#include<algorithm>
#include<queue>
(789)#include<map>
using namespace std;
struct ele                //记录层数
{
	string str;
	int step;
};
int BFS(string s)                  //广度搜索
{
	map<string, int> visited;        //访问标记数组
	queue<ele> con;            //保存数据队列
	ele k;
	k.str = s;
	k.step = 0;
	con.push(k);
	visited[s] = 1;
	int step = -1;

	while (!con.empty())
	{
		
	    ele z = con.front();
        con.pop();
		if (z.str.find("2012") != string::npos)
		{
			step = z.step;
			break;
		}
		else
		{
			z.step++;
			for (int i = 0; i < z.str.size() - 1; i++)
			{
				swap(z.str[i], z.str[i + 1]);
				if (visited.find(z.str) == visited.end())
				{
					con.push(z);
					visited[z.str] = 1;
				}
				swap(z.str[i], z.str[i + 1]);
			}
		}
	}
	return step;

}
int main()
{
	int n;
	while (cin >> n)
	{
		string s;
		cin >> s;
		cout << BFS(s) << endl;
	
	
	}

}


发表于 2020-03-24 14:53:35 回复(2)
BFS,字符串搜索优化,16ms
#include<string>
(765)#include<queue>
#include<iostream>
(720)#include<algorithm>
#include<unordered_map>
using namespace std;


bool find2012(string li, int start, int end) {
    for(int i=start; i<=end; ++i) 
        if(li[i]==50 && li[i+1]==48 && li[i+2]==49 && li[i+3]==50)
            return true;
    return false;
}


int BFS(string li, int size) {
    unordered_map<string, int> st;
    int count=0, start, end;
    queue<string> q;
    q.push(li);
    st[li]=1;
    while(!q.empty()) {
        int q_size=q.size();
        while(q_size--) {
            string tmp=q.front();
            q.pop();
            if(count==0 && find2012(tmp, 0, size-4)) return 0;
            else {
                for(int i=0; i<size-1; ++i) {
                    swap(tmp[i], tmp[i+1]);
                    start=max(0, i-3);
                    end=min(size-1, i+1);
                    if(st.find(tmp) == st.end()) {
                        if(find2012(tmp, start, end)) return count+1;
                        q.push(tmp);
                        st[tmp]=1;
                    }
                    swap(tmp[i], tmp[i+1]);
                }
            }
        }
        ++count;
    }
    return -1;
}


int main() {
    int n;
    string li;
    while(cin>>n) {
        cin>>li;
        if(count(li.begin(), li.end(), '2')<2 || count(li.begin(), li.end(), '0')<1 || count(li.begin(), li.end(), '1')<1) cout<<-1<<endl;
        else cout<<BFS(li, n)<<endl;
    }
}


发表于 2020-04-20 22:47:52 回复(0)

这道题跟玛雅人那道题一样,但测试用例似乎有点问题。

def BFS(Q,k,n,trash):
    m = len(Q)
    for j in range(m):
        q = Q.pop(0)
        trash.append(q)
        for i in range(n-1):          
            if '2012' in q[:i]+q[i+1]+q[i]+q[i+2:]:
                return k+1
            else:
                if q[:i]+q[i+1]+q[i]+q[i+2:] not in Q+trash:
                    Q.append(q[:i]+q[i+1]+q[i]+q[i+2:])
    return BFS(Q,k+1,n,trash)

while True:
    try:
        n = int(input())
        s = input()
        trash = []
        char_cnt = {'0':0,'1':0,'2':0}
        for i in range(n):
            char_cnt[s[i]] += 1
        if char_cnt['0']<1 or char_cnt['1']<1 or char_cnt['2']<1:
            print(-1)
        elif '2012' in s:
            print(0)
        else:
            print(BFS([s],0,n,trash))
    except:
        break
发表于 2020-01-05 12:33:15 回复(1)
//看了好久了没看出哪里有问题,烦请各位大佬帮忙指摘下,不胜感激啊
//思路是bfs

#include<iostream>
#include<string>
#include<queue>
#include<set>
using namespace std;

struct ele{
    string s;//对应的string
    int cnt;//由init的string经过ct次移位得到的
    ele(){}
    ele(string ss, int cc):s(ss), cnt(cc){}
};

int istrue(string s){
    if(s.find("2012")!=-1){
        return 1;
    }else{
        return 0;
    }
}

int main(){
    string s;
    int len, ct, i;
    while(cin>>len){
        cin>>s;
        //初步判断 不含有0 1 两个2
        if(s.size()<4 || s.find("0")==-1 || s.find("1")==-1 || s.find("2")==-1){
            cout<<-1<<endl;
            continue;
        }
        ct=0;
        for(i=0; i<len; i++){
            if(s[i]=='2')
                ct++;
        }
        if(ct<2){
            cout<<-1<<endl;
            continue;
        }

        ct=0;//记录移位次数
        queue<ele> q;
        q.push(ele(s, ct));
        string tp;
        ele e;
        int flag=0;
        set<string> st;

        while(!q.empty()){
            e=q.front();
            q.pop();
            if(st.count(e.s)){//访问过的不再访问了,记录的是相同string的情况下移位次数最少的那个
                continue;
            }else{
                st.insert(e.s);
            }

            if(istrue(e.s)){
                cout<<e.cnt<<endl;
                flag=1;
                break;
            }

            ct++;//移位
            for(i=0; i<e.s.size()-1; i++){
                tp=e.s;
                swap(tp[i], tp[i+1]);
                q.push(ele(tp, ct));
            }
        }
        if(flag==0){
            cout<<-1<<endl;
        }
    }
    return 0;
}

发表于 2019-08-25 15:01:26 回复(0)
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
struct N{    //转移状态
    string str;
    int t;    //转换次数
};
queue<N> Q;
map<string,int> M;
bool IsInMap(string s){    //s是否在map中
    if(M.find(s)==M.end()){
        M[s]=0;        //不在则插入
        return false;
    }
    else return true;
}
bool IsSolve(string s){
    if(s.find("2012",0)!=string::npos) return true;
    else return false;
}
void BFS(int n){    //n为字符串长度
    while(!Q.empty()){    //Q非空
        N nown=Q.front();
        Q.pop();
        string temp;
        for(int i=0;i<n-1;i++){
            temp=nown.str;    //取出当前状态
            swap(temp[i],temp[i+1]);    //交换
            if(IsInMap(temp)) continue;    //交换之后在map中已经存在了
            if(IsSolve(temp)){        //当前状态是目标
                cout<<nown.t+1<<endl;return;
            }
            //其他状态,入队
            N newn;
            newn.str=temp;newn.t=nown.t+1;
            Q.push(newn);
        }
    }
    cout<<-1<<endl;
}
int main(){
    int l;
    string str;
    while(cin>>l){
        while(!Q.empty()) Q.pop();
        M.clear();
        cin>>str;
        if(IsSolve(str)) cout<<0<<endl;    //不用转换
        else{
            M[str]=0;
            N f;
            f.str=str;f.t=0;
            Q.push(f);
            BFS(l);
        }
    }
}

发表于 2019-03-10 18:25:52 回复(0)
哥们不会搜索,手搓一个暴力迭代
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>

using namespace std;

static unordered_map<int, int> mp{
    {122, 2},
    {212, 1},
    {221, 2},
    {1022, 3},
    {1202, 2},
    {1220, 3},
    {2210, 3},
    {2201, 2},
    {2021, 1},
    {2120, 2},
    {2102, 1},
    {2012, 0},
};

int main()
{
    int N;
    string str;
    while (cin >> N >> str)
    {
        vector<int> vec[3] = {};
        for (int i = 0; i < N; i++)
            vec[str[i] - '0'].push_back(i);

        int ans = 1e9;
        for (int i = 0; i < vec[2].size(); i++)
        {
            int a = vec[2][i];
            for(auto b : vec[0])
                for(auto c : vec[1])
                    for(int j = i+1; j < vec[2].size(); j++)
                    {
                        int d = vec[2][j];
                        vector<int> tmp{a, b, c, d};
                        sort(tmp.begin(), tmp.end());
                        int key = (str[tmp[0]] - '0') * 1000 + (str[tmp[1]] - '0') * 100 
                            + (str[tmp[2]] - '0') * 10 + (str[tmp[3]] - '0');
                        ans = min(ans, tmp[3] - tmp[1] + tmp[2] - tmp[0] - 4 + mp[key]);
                    }
        }

        cout << (ans == 1000000000 ? -1 : ans) << "\n";
    }

    return 0;
}


发表于 2024-03-19 14:16:48 回复(0)
#include <iostream>
#include <queue>
#include <set>
#include <string>
using namespace std;

struct Node {
    string str; //字符串
    int depth;  //移位次数(广度优先搜索的深度)
    Node(string str, int depth): str(std::move(str)), depth(depth) {}
};

//判断字符串是否含有“2012”这几个字符
bool contain2012(string str) {
    if (str.length() < 4) {
        return false;
    }
    int count0 = 0,
        count1 = 0,
        count2 = 0; //统计‘0’、‘1’、‘2’字符的个数
    for (const auto& ch : str) {
        count0 += ch == '0';
        count1 += ch == '1';
        count2 += ch == '2';
    }
    return count0 >= 1 && count1 >= 1 && count2 >= 2;
}

//交换字符串str中下标为index和index+1的相邻字符
string swap_char(string str, int index) {
    swap(str[index], str[index + 1]);
    return str;
}

int main() {
    int n;
    string str;
    while (cin >> n >> str) {
        if (!contain2012(str)) {    //无解
            cout << -1 << endl;
            continue;
        }
        if (str.find("2012") != string::npos) { //无需移位
            cout << 0 << endl;
            continue;
        }
        queue<Node>myQueue;     //用于广度优先搜索的队列
        set<string>visited;     //标记已访问的字符串
        myQueue.push({str, 0});
        visited.insert(str);
        while (!myQueue.empty()) {
            Node current = myQueue.front();
            myQueue.pop();
            string str = current.str;
            int depth = current.depth + 1;
            for (int i = 0; i < n - 1; i++) {
                string str1 = swap_char(str, i);
                if (str1.find("2012") != string::npos) {
                    cout << depth << endl;
                    goto exit;  //作用相当于多重循环的break
                }
                if (visited.find(str1) == visited.end()) {
                    myQueue.push({str1, depth});
                    visited.insert(str1);
                }
            }
        }
exit:       //终止多重循环的出口
        ;
    }
    return 0;
}

发表于 2024-03-12 00:19:50 回复(0)
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
using namespace std;

struct code {
	string name;
	int num;
	code(string na,int n):name(na),num(n){}
};


int BFS(string str)
{
	map<string, bool> string_num;
	queue<code> q;
	q.push(code(str, 0));
	string_num[str] = true;
	while (!q.empty())
	{
		code current = q.front();
		q.pop();
		if (current.name.find("2012")!=string::npos)
		{
			return current.num;
		}
		for (int i = 0;i < current.name.size() - 1;i++)
		{
			{
				string next=current.name;
				swap(next[i], next[i + 1]);
				if (string_num.find(next) != string_num.end() && string_num[next]);
				else
				{
					q.push(code(next, current.num + 1));
					string_num[next] = true;
				}
			}
		}
	}
	return -1;
}


int main()
{
	string str;
	int n;
	while (cin >> n >> str)
	{
		printf("%d\n", BFS(str));
	}
	return 0;
}

发表于 2023-06-17 13:55:26 回复(0)
bfs,优化了一下,标记数组不要用map而要用unordered_map标记(耗时从600ms变到160ms),在判断要不要入队时,既要看有没有标记,也看当前步数,如果当前步数已经比得到的最小步数要高了,那就不需要入队(耗时直接从160ms变到16ms)
#include <algorithm>
#include <climits>
#include <cstdio>
#include <iostream>
#include <queue>
#include <string>
#include <unordered_map>
#include <vector>
#include <map>
using namespace std;

struct info{
    string s;
    int n;
    info(string s1,int n1){
        s=s1;n=n1;
    }
};
//unordered要比order快,因为只需要做个标记,不需要排序
unordered_map<string,int> mymap;
queue<info> myqueue;

int bfs(string s){
    mymap.clear();
    
    myqueue.push(info(s,0));
    mymap[s]++;
    int result=INT_MAX;
    while (!myqueue.empty()) {
        info temp=myqueue.front();
        myqueue.pop();
        
        int pos=temp.s.find("2012");
        if(pos!=string::npos){
            result=min(result,temp.n);
        }else{
            for(int i=0;i<temp.s.size()-1;i++){
                string temp2=temp.s;
                swap(temp2[i],temp2[i+1]);

                //temp.n+1<result这个判断最重要,如果当前的步数已经比result要高,就没必要继续遍历下去了
                if(mymap[temp2]==0&&temp.n+1<result){
                    myqueue.push({temp2,temp.n+1});
                    mymap[temp2]++;
                }
            }
        }
    }
    if(result==INT_MAX){
        result=-1;
    }
    return result;
}

int main() {
    int n;
    while (scanf("%d",&n)!=-1) {
        string s;
        cin>>s;
        cout<<bfs(s)<<endl;
    }
}



发表于 2023-02-24 14:39:25 回复(0)
#include <bits/stdc++.h>

using namespace std;
const int N=15;
int n;
string s;
bool st[N];
int minstep=1e9;
//dfs做***超时,对使用未超时的测试用例均正确
void dfs(int u, int step)
{
    if(u>n-1) return ;
    if(s.find("2012")!=-1)
    {
        minstep=min(minstep, step);
        return;
    }
        
    for(int i=0;i<s.size()-1;i++)
    {
        if(!st[i])
        {
            st[i]=true;
            swap(s[i],s[i+1]);
            dfs(u+1,step+1);
            swap(s[i],s[i+1]);
            st[i]=false;
        }
    }
}

int main()
{
    
    while(cin>>n>>s){
        
        memset(st, 0, sizeof st);
        minstep=1e9;
        dfs(0,0);
        if(minstep==1e9)
            cout<<-1<<endl;
        else
            cout<<minstep<<endl;
    }
    
   
    return 0;
}

发表于 2022-05-01 10:35:01 回复(0)
#include <iostream>
#include<queue>
#include<map>
using namespace std;

typedef struct Node{
    string str;//当前字符串
    int step;//第几次移位
}Node;

int bfs(string str){//广度优先
    queue<Node> q;//广度优先队列
    map<string,bool> visited;//该某字符是否被搜索过
    Node node;
    node.str=str;
    node.step=0;//第一个字符串移位次数为0
    q.push(node);
    int step=-1;//解不开密码的默认返回
    while(!q.empty()){//队列非空
        Node temp=q.front();//队头元素
        q.pop();
        string s=temp.str;//当前检查的字符串
        visited[s]=true;//令该字符串在map中有记录
        if(s.find("2012")==s.npos){//若当前字符串不包含2012
            for(int i=0;i<s.size()-1;i++){//进行n-1次交换
                swap(s[i],s[i+1]);//移位
                if(visited.find(s)==visited.end()&&visited[s]!=true){//移位后的字符串没有被访问过,要么没有加入map,要么不为true
                    Node x;
                    x.str=s;
                    x.step=temp.step+1;//次数加1
                    q.push(x);//入队
                }
                swap(s[i],s[i+1]);//还原
            }
        }else{
            step=temp.step;//找到目标字符串
            break;//注意找到后要终止循环
        }
    }
    return step;
}
int main()
{
    int n;
    while(cin>>n){
        string str;
        cin>>str;
        cout<<bfs(str)<<endl;//广度优先遍历
    }
    return 0;
}

发表于 2022-03-31 21:25:53 回复(0)
#include<iostream>
#include<queue>
#include<string>
#include<map>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
        string s;
        cin>>s;
        map<string,int> vis;
        queue<string> q;
        q.push(s);
        vis.insert(pair<string,int>(s,0));
        int flag=0;
        while(!q.empty())
        {
            string temp=q.front();
            q.pop();
            if(temp.find("2012")!=temp.npos)//找到
            {
                cout<<vis[temp]<<endl;
                flag=1;
                break;
            }
            else//没找到
            {
                for(int i=0;i<n-1;i++)
                {
                    string tt=temp;
                    char pp=tt[i];
                    tt[i]=tt[i+1];
                    tt[i+1]=pp;
                    if(vis.find(tt)==vis.end())
                    {
                        q.push(tt);
                        int k=vis[temp];
                        vis.insert(pair<string,int>(tt,k+1));
                    }
                }
            }
        }
        if(flag==0)
            cout<<"-1"<<endl;
    }
}
发表于 2021-09-11 16:33:21 回复(0)
from collections import deque
from copy import deepcopy


def switcher(s,level):
    ss = []
    for i in s:
        ss.append(i)
    
    result = []
    for i in range(len(ss)-1):
        new_one = deepcopy(ss)
        new_one[i+1] = ss[i]
        new_one[i] = ss[i+1]
        
        new_s = ''.join(new_one)
        result.append( (new_s,level+1) )
    return result
while True:
    try:
        m = input()
        orig_s = input().strip()
        if '2012' in orig_s:
            print(0)
            continue
        q = deque([])
        used = set()
        q.extend(switcher(orig_s,0))
        used.add(orig_s)
        #print(orig_s)
        while len(q) != 0:
            #print(q)
            one,level = q.popleft()
            if one in used:
                continue
            else:
                if '2012' in one:
                    print(level)
                    break
                else:
                    q.extend(switcher(one,level))
                    used.add(one)
        else:
            print(-1)
    except:
        break

发表于 2021-09-06 23:28:13 回复(0)
#include <cstdio>
#include <set>
#include <queue>
#include <string>
#include <map>

using namespace std;
set<string> already;
queue< pair<string, int> > q;
const string target("2012");
int n;

string exchangee(const string& s, int pos)
{
	string ret(s);
	auto t = ret[pos];
	ret[pos] = ret[pos-1];
	ret[pos-1] = t;
	return ret; 
}
void init()
{
	already.clear();
	while(!q.empty()) q.pop();
}
void BFS(const string& s0)
{
	q.push(make_pair(s0, 0));
	already.insert(s0);
	while(!q.empty())
	{
		auto now = q.front(); q.pop();
		string nows = now.first;
		if(nows.find(target) != nows.npos)
		{
			printf("%d\n", now.second,nows.c_str());
			return;
		}
		for(auto i = nows.size()-1; i > 0; --i)
		{
			auto te = exchangee(nows, i);
			{
				if(already.insert(te).second)
				{
					q.push(make_pair(te, now.second+1));	
				}	
			}	
		}	
	}
	printf("-1\n");
}
int main()
{
	while(scanf("%d", &n) != EOF)
	{
		if(n==0) break;
		init();
		string si;
		si.clear();
		getchar();
		for(int i = 0; i<n;++i)
		{
			char temp;
			scanf("%c", &temp);
			si.push_back(temp);
		}
		getchar();
		BFS(si);
	}
 } 

发表于 2020-09-03 01:59:31 回复(0)
第一眼看上去,题中给的思路就很明显,每一个字符串都有它的长度减1中状态,求最少的步骤当然用BFS了,我个人比较喜欢优先队列搜索,然后用一个map映射一下,看是否这个状态出现过,若是出现当然就不用搜下去了,否则就是无限循环。附上AC代码
#include<bits/stdc++.h>
using namespace std;
struct node{
    string s;
    int t;
    bool operator<(const node &rs)const{//步数少的在优先队列前面。
        return t>rs.t;
    }
};
string str;
int bfs(){
    priority_queue<node>q;
    map<string,int>mp;
    mp[str] = 1;
    q.push({str,0});
    while(!q.empty()){
        node now = q.top();q.pop();
        if(now.s.find("2012")!=string::npos){
            return now.t;
        }
        for(int i = 0;i<now.s.size()-1;i++){
            swap(now.s[i],now.s[i+1]);
            if(mp.count(now.s)){
                swap(now.s[i],now.s[i+1]);
                continue;
            }
            mp[now.s] = 1;
            q.push({now.s,now.t+1});
            swap(now.s[i],now.s[i+1]);
        }
    }
    return -1;
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        cin>>str;
        printf("%d\n",bfs());
	}
}

发表于 2020-04-26 10:20:51 回复(0)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            //移位
        	int n=sc.nextInt();
        	String code=sc.next();
        	int moveTime=getMoveTime(code);
        	System.out.println(moveTime);
        	
        }
    }

	private static int getMoveTime(String code) {
		if(code.length()<4)return -1;
		List<String>record=new ArrayList<>();//记录已经交换过的结果,剪枝。
		Queue<Help>queue=new LinkedList<>();
		Help help=new Help(code,0);
		queue.offer(help);
		record.add(code);
		while(!queue.isEmpty()) {
			help=queue.poll();
			if(help.s.contains("2012"))
				return help.cnt;
			for(int i=0;i<code.length()-1;i++) {
				char[]arr=help.s.toCharArray();
				char temp = arr[i];
		        arr[i] = arr[i+1];
		        arr[i+1] = temp;
		        String after=new String(arr);
		        if(!record.contains(after)) {
		        	record.add(after);
		        	queue.offer(new Help(after,help.cnt+1));
		        }
			}
		}
		return -1;
	}
}
class Help{
	String s;
	int cnt;
	Help(String s,int cnt){
		this.s=s;
		this.cnt=cnt;//交换次数
}


发表于 2020-04-07 14:55:49 回复(0)
思路是BFS
#include <iostream>
(720)#include <vector>
#include <map>
(747)#include <algorithm>
#include <iterator>
(2102)#include <cmath>
#include <set>
(855)#include <cstdio>
#include <cstdlib>
(895)#include <stack>
#include <queue>
(789)#define PI acos(-1)
using namespace std;

typedef struct Node{
    string state="";//状态
    //int id;//标识
    int t=0;//移动次数
}Node;
int fun(string str){
    //根据输入的str,以三进制的形式输出其对应的数值
    int id=0;
    int l=str.length();
    int i;
    int x;
    for(i=0;i<l;i++){
        x=str[i]-'0';
        id+=x*pow(3,l-i-1);
    }
    return id;
}

int BFS(string str){
    //采用广度优先搜索得到结果
    int l=str.length();//获取字符串长度
    if(str.find("2012")<l)return 0;
    int sizes=pow(3,l);//标技数组的长度
    int i;
    bool mark[sizes];
    for(i=0;i<sizes;i++){
        mark[i]=false;//该状态未被使用
    }
    queue<Node>q;//状态队列
    Node first;
    first.t=0;
    first.state=str;
    int id=fun(str);
    mark[id]=true;
    q.push(first);
    while(!q.empty()){
        //队列不为空
        Node now=q.front();//出队列
        q.pop();//出队列
        //cout<<now.state<<"出队列"<<endl;
        //状态扩展,任意交换相邻的两个字符
        for(i=0;i<l-1;i++){
            string nextstate=now.state;
            char ctmp=nextstate[i];
            nextstate[i]=nextstate[i+1];
            nextstate[i+1]=ctmp;//交换
            int nextt=now.t+1;
            int isexit=nextstate.find("2012");
            if(isexit!=-1){
                //目标状态
                return nextt;
            }
            int nextid=fun(nextstate);//计算状态值
            if(mark[nextid])continue;//说明该状态已经遍历过
            Node next;//构造新状态
            next.state=nextstate;
            next.t=nextt;
            q.push(next);
            //cout<<nextstate<<"入栈"<<endl;
            mark[nextid]=true;
        }
    }
    //直到队列为空都没能找到目标状态,则说明不存在
    return -1;
}
int main(){
    int n;
    string str;
    while(cin>>n){
        cin>>str;
        int ans=-1;
        int i;
        int znum=0;
        int onum=0;
        int tnum=0;
        for(i=0;i<str.length();i++){
            if(str[i]=='0'){
                znum++;
            }else if(str[i]=='1'){
                onum++;
            }else if(str[i]=='2'){
                tnum++;
            }
        }
        if(onum>=1&&znum>=1&&tnum>=2){
            //先做一个简单的排除,如果字符串中含有的0,1,2不能满足2012,直接排除
            ans=BFS(str);
        }else{

        }
        cout<<ans<<endl;
    }
    return 0;
}

发表于 2020-03-21 12:32:09 回复(0)
#include <iostream>
#include <queue>
#include <string>
#include <unordered_set>
using namespace std;

/*
思路:BFS
*/
//当前str一次变化后字符串vec
vector<string> nextChangeStrVec(string str) {
    vector<string> results;
    for (int i = 1; i < str.size(); i++) {
        swap(str[i], str[i - 1]);
        results.push_back(str);
        swap(str[i], str[i - 1]);        
    }

    return results;
}

int main() {
    int n;
    while (cin >> n) {
        string str;
        cin >> str;
        queue<string> que;
        unordered_set<string> set; //标记str是否已经处理过
        que.push(str);
        set.insert(str);

        int change = 0;
        int flag = 0; //是否找到第一个2012
        while (!que.empty()) {
            if (flag)
                break;

            int size = que.size(); //由于size动态变化,先取出值
            ++change; //每层结果+1
            //分层
            for (int i = 0; i < size; i++) {
                string front = que.front();
                que.pop();

                if (front.find("2012") != -1) {
                    flag = 1;
                }

                vector<string> nexts = nextChangeStrVec(front);
                for (auto str: nexts) {
                    if (set.find(str) != set.end())
                        continue;

                    que.push(str);
                    set.insert(str);
                }
            }
        }

        if (flag)
            cout << change - 1 << endl;
        else
            cout << -1 << endl;
    }
}
编辑于 2019-08-23 15:47:07 回复(0)
//BFS AK!!
#include <iostream>
#include <queue>
#include <string>
#include <map>
using namespace std;

struct Node{
    string str;
    int level;

};

bool check(string str){
    return (str.find("2012",0)!=string::npos);
}

map<string,bool>M;
queue<Node>Q;
int main()
{
    int n;
    string str;
    int ans=0;
    bool flag=false;
    while(cin>>n){
        flag=false;
        ans=0;
        cin>>str;
        while(!Q.empty())Q.pop();
        M.clear();

        Node tmp;
        tmp.str=str;tmp.level=0;
        M[str]=true;
        Q.push(tmp);

        while(!Q.empty()){
            tmp=Q.front();
            Q.pop();
            if(check(tmp.str)){
                ans=tmp.level;
                flag=true;
                break;

            }
            for(int i=0;i<n-1;i++){//两两交换位置
                swap(tmp.str[i],tmp.str[i+1]);
                if(!M[tmp.str]){
                    tmp.level+=1;
                    Q.push(tmp);
                    M[tmp.str]=true;

                    tmp.level-=1;//再变回来
                }
                swap(tmp.str[i],tmp.str[i+1]);//换回来
            }

        }
        if(flag)cout<<ans<<endl;
        else cout<<-1<<endl;

    }
    return 0;
}

发表于 2019-04-01 20:07:01 回复(1)