HDU4474(搜索思想)

本文介绍了一种利用广度优先搜索(BFS)解决特定数学问题的方法:寻找一个正整数,该数模n等于0,并且不包含特定禁止出现的数字。通过将问题转化为搜索余数空间,确保了算法的高效性和正确性。

    先贴一发,还不是太理解

    /**
     * 比较巧的广搜+记录最短路径
     * 搜余数,骚的一匹。。。
     * 用余数做结点,复杂度10000
     * 复习题
     * n1 mod k = (n1 mod k) mod k
     * (n1 + n2) mod k = ((n1 mod k) + (n2 mod k)) mod k
     * (n1 * w) mod k = ((n1 mod k) * w) mod k
     * 已保证先搜到的是最小的。
     */
    
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    const int mmax = 10002;
    
    bool book[mmax];
    bool unincluded[11];
    
    int n;
    
    char route[mmax];//字符串输出,每个下标(余数)只存一位数,也可以用int
    int pre[mmax];
    
    bool bfs()
    {
        queue<int> Q;
        Q.push(0);//先放一个数,为何放0
        int now;//代表余数,其实本来是要代表的未取余的数,但经过证明可以用余数代替。
    
        while(!Q.empty())
        {
            now = Q.front();
            Q.pop();
    
            for(int i = 0; i < 10; i++)//必须从0开始,遍历数字0-9
            {
                if(unincluded[i])//不允许使用的数字
                    continue;
                if(now == 0 && i == 0)//排除第一个??
                    continue;
    
                int next = (now * 10 + i)%n;//下一个余数
    
                if(book[next])//如果余数用过,则不加入,剪枝
                    continue;
    
                route[next] = '0' + i;
                book[next] = true;
                pre[next] = now;//记录到达这个余数前面的余数
                Q.push(next);
                if(next == 0)//可以放到开头
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    void out()
    {
        int p = 0;
        string output;
        while(p != 0 || output.empty())
        {
            output += route[p];
            p = pre[p];
        }
        reverse(output.begin(), output.end());
        puts(output.c_str());//c语言遗留的,书上写的,返回指针
    }
    
    int t;
    int main()
    {
        int m;
        t = 1;
        while(scanf("%d%d", &n, &m) != EOF)
        {
            memset(unincluded, 0, sizeof(unincluded));
            memset(book, 0, sizeof(book));
    
            int num;
            for(int i = 1; i <= m; i++)
            {
                scanf("%d", &num);
                unincluded[num] = true;
            }
    
            printf("Case %d: ", t);
    
            if(bfs())
            {
                out();
            }
            else
            {
                printf("-1\n");
            }
            t++;
        }
    
        return 0;
    }
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值