搜索一个是n倍数的大数,bfs
求一个大数,满足是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;
}
浙公网安备 33010602011771号