九度oj 题目1482:玛雅人的密码 清华大学机试

题目描述:

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。

输入:

输入包含多组测试数据,每组测试数据由两行组成。
第一行为一个整数N,代表字符串的长度(2<=N<=13)。
第二行为一个仅由0、1、2组成的,长度为N的字符串。

输出:

对于每组测试数据,若可以解出密码,输出最少的移位次数;否则输出-1。

样例输入:
5
02120
样例输出:
1

这个题第一眼看上去好像不难,但做起来却不知道如何下手。一开始思路往动态规划上靠,可是状态转移方程真实难以想明白。
想了很久,实在是想不明白,只好翻了翻别人的题解,这才知道原来是用广度优先搜索来做。
一道题找对方法真的很重要。

那么搜索时状态即为字符串的排列情况,利用map来记录该状态是否被访问过。检查每一个状态是否符合要求,一旦符合,就是最小的次数。

代码如下
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <string>
 5 #include <map>
 6 #include <queue>
 7 
 8 using namespace std;
 9 int cnt[3];
10 typedef pair<string, int> Node;
11 map <string, int> mapping;
12 
13 string str;
14 queue <Node> que;
15 
16 bool isOk(string s) {
17     int len = s.size();
18     for (int i = 0; i <= len-4; i++) {
19         if (s[i] == '2' && s[i + 1] == '0' && s[i + 2] == '1' && s[i + 3] == '2') {
20             return true;
21         }
22     }
23     return false;
24 }
25 
26 int main() {
27     int n;
28     while (scanf("%d", &n) != EOF) {
29         cin >> str;
30         int len = str.size();
31         memset(cnt, 0, sizeof(cnt));
32         for (int i = 0; i < len; i++) {
33             cnt[str[i] - '0']++;
34         }
35         if (cnt[0] < 1 || cnt[1] < 1 || cnt[2] < 2) {
36             puts("-1");
37             continue;
38         }
39         while (!que.empty()) {
40             que.pop();
41         }
42         mapping.clear();
43         mapping[str] = 1;
44         que.push(Node(str, 0));
45         int ans = -1;
46         while (!que.empty()) {
47             Node p = que.front(); que.pop();
48             string t = p.first;
49             int step = p.second;
50             if (isOk(t)) {
51                 ans = step;
52                 break;
53             }
54             for (int i = 0; i+1 < len; i++) {
55                 string tmp = t;
56                 swap(tmp[i], tmp[i + 1]);
57                 if (mapping.find(tmp) == mapping.end()) {
58                     mapping[tmp] = 1;
59                     que.push(Node(tmp, step + 1));
60                 }
61             }
62 
63         }
64         printf("%d
", ans);
65         
66     }
67     return 0;
68 }

这种题题面很简单,做起来代码其实也很简单,但就是想不到该用什么样的方法,但一旦找对方法,问题就迎刃而解了

原文地址:https://www.cnblogs.com/jasonJie/p/5881959.html