zoukankan      html  css  js  c++  java
  • HDOJ 1226 超级密码(bfs)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1226

    思路分析题目要求寻找一串长度不大于500的C进制的密码,且该密码需要为十进制数N的整数倍。

    <1>搜索方式选择:由于密码的长度未知(题目限制最大为500),所以状态树的深度比较深,采用dfs搜索效率比较低,选择bfs搜索更好。

    <2>剪枝方法:题目中对于每个状态需要采用模运算判断是否为N的整数倍;

    由模运算的性质:设存在两个整数a和b,如果a%n==b%n,那么(a*x+c)%n==(b*x+c)%n;

    所以如果在搜索的过程出现了某个状态取模的余数与前面某个状态取模的余数相同的情况,那么这个状态被剪枝,不需要延伸下去;

    <3>注意事项:对于判断某个数是否为N的倍数的方法中,因为密码的十进制数可能太大导致无法存储,需要借助模运算的性质:

    (a + b) % p = (a % p + b % p) % p

    (a - b) % p = (a % p - b % p) % p

    (a * b) % p = ((a % p) * (b % p)) % p

    (a ^ b) % p = ((a % p) ^ b) % p

    代码如下:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int MAX_N = 500 + 10;
    const int MAX_M = 5000 + 50;
    
    struct Node
    {
        int num[MAX_N];
        int len;
    };
    bool digit[22];
    bool mark[MAX_M];
    int N, C, M;
    
    int Judge(Node &p)
    {
        int len = p.len;
        int temp = 0;
    
        for (int i = 0; i <= len; ++i)
            temp = (temp * C + p.num[i]) % N;
        return temp;
    }
    
    bool Bfs()
    {
        Node p;
        queue<Node>Q;
    
        p.len = 0;
        Q.push(p);
        while (!Q.empty())
        {
            p = Q.front();
            Q.pop();
    
            for (int i = (p.len == 0 ? 1 : 0); i < 16; ++i)
            {
                if (digit[i])
                {
                    int mod = 0;
                    Node q = p;
    
                    q.num[q.len] = i;
                    mod = Judge(q);
    
                    if (mod && !mark[mod] && q.len + 1 <= 500)
                    {
                        mark[mod] = true;
                        q.len += 1;
                        Q.push(q);
                    }
                    else if(mod == 0)
                    {
                        for (int i = 0; i <= q.len; ++i)
                            printf("%X", q.num[i]);
                        printf("
    ");
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    
    int main()
    {
        int case_times;
    
        scanf("%d", &case_times);
        while (case_times--)
        {
            int temp_value;
    
            scanf("%d%d%d", &N, &C, &M);
            memset(digit, false, sizeof(digit));
            memset(mark, false, sizeof(mark));
            for (int i = 0; i < M; ++i)
            {
                scanf("%x", &temp_value);
                digit[temp_value] = true;
            }
    
            if (N == 0 && digit[0])
                printf("0
    ");
            else if (N == 0 && !digit[0])
                printf("give me the bomb please
    ");
            else if (!Bfs())
                printf("give me the bomb please
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    idea 使用 maven 下载 jar 包,出现证书校验问题问题
    接口抽象类区别,Java中IO,BIO、NIO、AIO区别以及Files的常用方法
    JIT编译器,Java平台的不同及Java一次编写,随处运行
    什么是Java虚拟机,JVM分配的不同类型内存区域是什么?
    AOP底层原理及AOP操作
    抽象类能使用 final 修饰吗?
    抽象类必须要有抽象方法吗?
    String 类的常用方法都有那些?
    普通类和抽象类有哪些区别?
    如何将字符串反转?
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4474803.html
Copyright © 2011-2022 走看看