zoukankan      html  css  js  c++  java
  • 九度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
    来源:
    2012年清华大学计算机研究生机试真题

    思路:

      hash + BFS。

      BFS的题目经常搭配着hash,BFS题目最终要的一点是”剪枝“,假如不适当的剪枝可能会超时,这里用hash数组进行剪枝是一个好的方法。

           本题中hash采用三进制——因为字符串中只有0、1、2,对所有的字符串状态进行标记。

           和这个有些相似的题目有CCF 201604-4 游戏,也采用了状态标记的方法进行剪枝。

    #include <iostream>
    #include <stdio.h>
    #include <string>
    #include <math.h>
    #include <deque>
    #include <memory.h>
    using namespace std;
    
    string str;
    int N;
    
    bool visited[1600000];
    
    bool match(const string &str1) {
    
        for(int i = 0; i <= N-4; i ++) {
            if(str1.substr(i, 4) == "2012")
                return true;
        }
        return false;
    }
    
    int hash_func(string cur) {
        int res = 0;
        for(int i = 0; i < N; i ++)
            res = res*3+cur[i]-'0';
        return res;
    }
    
    int main() {
        while(scanf("%d", &N) != EOF) {
            cin >> str;
            memset(visited, 0, sizeof(visited));
    
            deque<string> record;
            record.push_back(str);
            int cur_lel = 1, nxt_lel = 0, ret = 0;
            bool found = false;
    
            while(!record.empty()) {
                string cur = record.front();
                record.pop_front();
                cur_lel --;
    
                if(match(cur)) {
                    found = true;
                    cout << ret << endl;
                    break;
                }
    
                for(int i = 0; i < N-1; i ++) {
                    swap(cur[i], cur[i+1]);
                    int hash_val = hash_func(cur);
                    if(!visited[hash_val]) {
                        visited[hash_val] = true;
                        record.push_back(cur);
                        nxt_lel ++;
                    }
                    swap(cur[i], cur[i+1]);
                }
    
                if(cur_lel == 0) {
                    cur_lel = nxt_lel;
                    nxt_lel = 0;
                    ret ++;
                }
    
            }
            if(!found)
                cout << -1 << endl;
        }
        return 0;
    }
  • 相关阅读:
    Python爬取中国疫情的实时数据
    文件上传
    条件查询和分页(第三周)
    全国疫情可视化图表
    Jquery的Ajax技术(第二周)
    软件工程开课博客
    求一个整数数组、环形数组中最大子数组的和
    今日所学—Android中ViewPager的使用
    今日所学—Android中ExpandableListView的使用
    你看,蚂蚁金服都上市了,程序员什么时候才能财富自由呢?
  • 原文地址:https://www.cnblogs.com/starryxsky/p/7285882.html
Copyright © 2011-2022 走看看