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("\n");
                    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\n");
        else if (N == 0 && !digit[0])
            printf("give me the bomb please\n");
        else if (!Bfs())
            printf("give me the bomb please\n");
    }

    return 0;
}
时间: 2024-08-01 22:43:06

HDOJ 1226 超级密码(bfs)的相关文章

hdoj 1226 超级密码 【隐式图BFS】

题目:hdoj 1226 超级密码 分析:这题属于隐式图搜索,状态不是很明显,需要自己建立. 其实搜索说白了就是暴力. 这个题目就是,首先对给出的可以组成的所有的数依次枚举,长度从小到大. 比如第一组样例,因为0不能出现在首位,那么我们枚举首位为1 和 7 看看漫步满足, 满足的话枚举第二位10 11 17 以及 70 71 77 顺便保存他们取余 n 之后的值,这样就可以剪枝,搜索过的就不用重复搜索了. 要求最早出现的BFS即可,第一个搜到的就是. 注意长度不大于500 AC代码: #incl

hdu 1226 超级密码 BFS 挺不错的题啊!

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2883    Accepted Submission(s): 928 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的

hdu 1226 超级密码 bfs+取余判重

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2808    Accepted Submission(s): 897 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的

hdu - 1226 超级密码 (bfs)

http://acm.hdu.edu.cn/showproblem.php?pid=1226 难以想到怎么去bfs,还是对状态的划分不明确,知道了之后感觉还是挺简单的. 这题关键是密码可能很长,然后判断是否整除用到了一点技巧,确保不会溢出,输出的时候是用递归回溯输出. 因为同一个数可以取多次,而最终取的是数值最小的,故输入之后从小到大排序,然后从第一个数到最后一个数每次添加一遍,直到找到合适的为止. 为了便于输出用了数组模拟队列. 1 #include <cstdio> 2 #include

hdu 1226 超级密码

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3110    Accepted Submission(s): 1006 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制

超级密码(bfs)

超级密码 Time Limit : 20000/10000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 4   Accepted Submission(s) : 0 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:密 码是一个C进制的数,并且只能由

超级密码(dfs)

超级密码233 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3406    Accepted Submission(s): 1080 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:密码是一个C进

中兴F412光猫超级密码破解、破解用户限制、关闭远程控制、恢复路由器拨号

不少家庭都改了光纤入户,那肯定少不了光猫的吧.今天以中兴F412光猫为例介绍下此型号光猫超级密码的破解方法.一.F412超级密码破解方法1.运行CMD,输入telnet 192.168.1.1: 2.连接成功后,会出现F412 login:提示登陆帐号和密码,帐号root密码root或Zte521(以前是root 现在很多都是Zte521了),输入密码的时候不会有字符提示 输入root回车Zte521回车 3.登陆成功后,会提示busybox的版本,这里可以进行shell操作了 4.输入send

hdoj 2041 超级阶梯

代码: #include <stdio.h>int main(){int n;int i;int m;int count;int dp[50];while(scanf("%d",&n)!=EOF){dp[1]=1;dp[2]=1;dp[3]=2;while(n--){count=0;scanf("%d",&m);for(i=4; i<=m; i++){dp[i]=dp[i-1]+dp[i-2];}printf("%d\n&