HDU 1226 BFS

HDU 1226

题目链接:

题意:

求一串密码。密码的规则即密码是c进制的,且能被n整除的最小值。密码最多500位,超出后不合法。密码可能由m中数字任意组成。

思路:

有没有那种写过一次不想再写一次的题。

有,比如这题。

需要特判0的情况。

需要记录已经出现了余数的情况,用来剪枝。

 

源码:

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <iostream>

#include <queue>

using namespace std;

int base[20], vis[5000+5];

struct Lv

{

    int len;

    int out[500+5];

    int val;

    Lv(){len = 0;}

    Lv(int _val){out[0] = val = _val; len = 1; }

}ans;

queue<Lv>que;

void output(Lv lv)

{

    for(int i = 0 ; i < lv.len ; i++){

        if(lv.out[i] >= 0 && lv.out[i] <= 9)

            printf("%c", lv.out[i] + '0');

        else

            printf("%c", lv.out[i] - 10 + 'A');

    }

    printf("\n");

}

void cmp(int ok, Lv org)

{

    if(ok == 0){

        for(int i = 0 ; i < org.len ; i++)

            ans.out[i] = org.out[i];

        ans.len = org.len;

    }

    else{

        for(int i = 0 ; i < org.len ; i++){

            if(ans.out[i] > org.out[i])

                cmp(0, org);

            else if(ans.out[i] < org.out[i])

                return;

        }

    }

}

bool BFS(int c, int n)

{

    int ok = 0;

    while(!que.empty()){

        Lv org = que.front();   que.pop();

        for(int i = 0 ; i < 16 ; i++){

            if(base[i]){

                int tval = org.val;

                org.val = (org.val * c + i) % n;

                org.out[org.len++] = i;

                if(org.val == 0){

                    cmp(0, org);

                    return true;

                }

                if(org.len <= 499 && vis[org.val] == 0)

                    que.push(org);

                vis[org.val] = 1;

                org.len--;

                org.val = tval;

            }

        }

    }

    return false;

}

int main()

{

    int t;

    scanf("%d", &t);

    while(t--){

        int n, c, m;

        scanf("%d%d%d", &n, &c, &m);

        if(n == 0){

            int mmin = c;

            char sstr[4];

            for(int i = 0 ; i < m ; i++){

                scanf("%s", sstr);

                int temp;

                if(sstr[0] >= 'A' && sstr[0] <= 'F')

                    temp = sstr[0] - 'A' + 10;

                else

                    temp = sstr[0] - '0';

                mmin = min(mmin, temp);

            }

            if(mmin == 0)

                printf("%d\n", mmin);

            else{

                printf("give me the bomb please\n");

            }

            continue;

        }

        memset(base, 0, sizeof(base));

        memset(vis, 0, sizeof(vis));

        while(!que.empty())

            que.pop();

        int ok = 0;

        int res = n;

        for(int i = 0 ; i < m ; i++){

            char sstr[4];

            scanf("%s", sstr);

            int temp;

            if(sstr[0] >= 'A' && sstr[0] <= 'F')

                temp = sstr[0] - 'A' + 10;

            else

                temp = sstr[0] - '0';

            vis[temp % n] = 1;

            if(temp % n == 0 && temp != 0){

                ok = 1;

                res = min(res, temp);

            }

            if(base[temp%n] == 0){

                base[temp] = 1;

                if(temp != 0){

                    Lv lv = Lv(temp%n);

                }

            }

        }

        for(int i = 1 ; i < 16 ; i++){

            if(base[i]){

                Lv lv = Lv(i);

                que.push(lv);

            }

        }

        if(ok){

            printf("%d\n", res);

            continue;

        }

        ok = BFS(c, n);

        if(!ok)

            printf("give me the bomb please\n");

        else

            output(ans);

    }

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值