HDU1226-超级密码(BFS)

 

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

 

 

题目大意:求一个数,它是由M个数字组成,是C进制,且是N(10进制整数)的整数倍。求这个数的最小值。

例如N=22,C=10,M=3,三个数字是7,0,1;那么满足由7,0,1组成的10进制数且是22的倍数的最小值是110。

 

 

由于求的数是最小的,用bfs比dfs更好一些。用bfs实现由数字组成的数按从小到大放入队列中,如果满足题目要求的条件,就输出并退出。密码最多有500位,必须用数组存储这个数。在判断这个数是否是N的倍数时,要用剩余定理。

(a+b)%n = a%n + b%n

 

 

例如我想判断16进制的数CCB是否是10进制数25的倍数(C是12,B是11)我们从高位向低位依次计算:

(12*16+12)%25 = 4

(4*16+11)%25 = 0

所以CCB是25的倍数。

 

剪枝:因为通过bfs产生的数是从小到大产生的,所以如果两个数(两个数肯定是一大一小)取模的余数相等了话,在以后的bfs中这两个数的变化是相同的,而题目求的是最小的数,较大的数就不用再进行bfs了。

 

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
int digit[20];
int vis[5010];
int T,N,C,M;
struct node
{
    int num[510];
    int len;
};
int judge(node p)
{
    int t = 0;
    for(int i=0; i<p.len; i++)
        t = (t * C +p.num[i]) % N;
    return t;
}
int bfs()
{
    queue<node>Q;
    node p,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] && p.len<=500)
            {
                q = p;
                q.num[q.len] = i;
                q.len++;

                if(judge(q)==0)
                {
                    for(int i=0; i<q.len; i++)
                        printf("%X",q.num[i]);
                    cout<<endl;
                    return 1;
                }
                if(!vis[judge(q)])
                {
                    vis[judge(q)] = 1;
                    Q.push(q);
                }

            }
        }
    }
    return 0;

}
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>N>>C>>M;
        memset(digit,0,sizeof(digit));
        memset(vis,0,sizeof(vis));
        int t;
        for(int i=0; i<M; i++)
        {
            scanf("%x",&t);
            digit[t] = 1;
        }
        if( N==0 && digit[0] ) //只有0才是0的正整数倍
            cout<<0<<endl;
        else if( N==0 && !digit[0] ) //如果构成的数字没有0,则没有0这个密码构成
            cout<<"give me the bomb please"<<endl;
        else if(!bfs())
            cout<<"give me the bomb please"<<endl;

    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值