搜索一个是n倍数的大数,bfs

hdoj 1226 超级密码

求一个大数,满足是n的倍数,但是长度不超过500位。一开始以为搜索的状态有m^500,觉得无从下手。其实我们可以运用同模定理,所以状态最多是n,从0到n-1。

还有这里要保存路径,所以用数组来模拟队列,每个节点记录他父亲节点在数组队列中的下标值。

总结:1.大数问题,特别是涉及到倍数方面的,考虑下取模运算。

         2.bfs搜索求路径时,用数组模拟队列取代queue。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

struct Node {
    int val, mod; //记录当前点的值与对n的取模值
    int idx, pre; //记录当前点的下标与父亲节点的下标
    int deep;     //记录深度,即数字的长度
}ns[500005];

int end, n, type, m;
int num[20];



void init() {
    int i;
    char ch[10];
    scanf( "%d %d", &n, &type );
    scanf( "%d", &m );
    for( i=1; i<=m; ++i ) {
        scanf( "%s", ch );
        if( ch[0] >= 'A' && ch[0] <= 'F' ) num[i] = 10 + ch[0] - 'A';
        else num[i] = ch[0] - '0';
    }
}


bool canEnd() {
    bool flag = false;
    for(int i=1; i<=m; ++i ) if( num[i] == 0 ) flag = true;
    if( n == 0 ) {
        if( flag ) printf( "0\n" );
        else puts( "give me the bomb please" );
        return 1;
    }
    return 0;
}


void output( int s ) {
    if( ns[s].pre != s ) output( ns[s].pre );
    printf( "%X", ns[s].val );
}


void solve() {
    int i, j, head, mm;
    bool mark[5001];
    Node p, q;
    if( canEnd() ) return;
    memset( mark, 0, sizeof(mark) );
    sort( num+1, num+m+1 );
    end = 0;
    for( i=1; i<=m; ++i ) {
        if( num[i] == 0 ) continue;
        ns[end].val = num[i]; 
        ns[end].mod = num[i] % n;
        ns[end].idx = ns[end].pre = end;
        ns[end].deep = 1;
        mark[ns[end].mod] = 1;
        ++ end;
    }
    head = 0;
    while( head < end ) {
        p = ns[head];
        ++head;
		if( p.mod == 0 ) {
			output( p.idx );
			printf( "\n" );
			return;
		}
        for( i=1; i<=m; ++i ) {
            q.val = num[i];
            q.mod = (p.mod*type + num[i]) % n;
            q.idx = end;
            q.pre = p.idx;
            q.deep = p.deep + 1;
            if( mark[q.mod] ) continue;
            if( q.deep >= 500 && q.mod != 0 ) continue;
            ns[end++] = q;
            mark[q.mod] = 1;
        }
    }
    puts( "give me the bomb please" );
}


int main() {
//    freopen( "c:/aaa.txt", "r", stdin );
    int T;
    scanf( "%d", &T );
    while( T-- ) {
        init();
        solve();
    }
    return 0;
}

posted on 2011-03-26 14:13  CrazyAC  阅读(276)  评论(0编辑  收藏  举报