HDU1226超级密码(宽搜+记忆化搜索)

B - 超级密码
Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:
密码是一个C进制的数,并且只能由给定的M个数字构成,同时密码是一个给定十进制整数N(0<=N<=5000)的正整数倍(如果存在多个满足条件的数,那么最小的那个就是密码),如果这样的密码存在,那么当你输入它以后门将打开,如果不存在这样的密码......那就把门炸了吧.

注意:由于宝藏的历史久远,当时的系统最多只能保存500位密码.因此如果得到的密码长度大于500也不能用来开启房门,这种情况也被认为密码不存在.
 

Input

输入数据的第一行是一个整数T(1<=T<=300),表示测试数据的数量.每组测试数据的第一行是两个整数N(0<=N<=5000)和C(2<=C<=16),其中N表示的是题目描述中的给定十进制整数,C是密码的进制数.测试数据的第二行是一个整数M(1<=M<=16),它表示构成密码的数字的数量,然后是M个数字用来表示构成密码的数字.两个测试数据之间会有一个空行隔开.

注意:在给出的M个数字中,如果存在超过10的数,我们约定用A来表示10,B来表示11,C来表示12,D来表示13,E来表示14,F来表示15.我保证输入数据都是合法的.
 

Output

对于每组测试数据,如果存在要求的密码,则输出该密码,如果密码不存在,则输出"give me the bomb please".

注意:构成密码的数字不一定全部都要用上;密码有可能非常长,不要试图用一个整型变量来保存密码;我保证密码最高位不为0(除非密码本身就是0).
 

Sample Input

       
       
3 22 10 3 7 0 1 2 10 1 1 25 16 3 A B C
 

Sample Output

       
       
110 give me the bomb please CCB

Hint

Hint 
Huge input, scanf is recommended.
 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<string>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=20+5;
int done[5005],n,type,m,i,win;
int da[17];

struct node
{
	int key,pre,yu,place;
}p[100000];
void showpath(int id)
{
	if(!id)return ;
	showpath(p[id].pre);
	if(p[id].key>=10)printf("%c",p[id].key-10+'A');
	else printf("%d",p[id].key);
}
void bfs()
{
	win=0;
	queue<int>q;
	memset(done,0,sizeof(done));
	int cnt=0;
	p[0].pre=-1;
	p[0].yu=0;
	p[0].place=0;
	q.push(cnt++);
	while(!q.empty())
	{
		int id=q.front();q.pop();
		if(p[id].place==500)return ;
		for(i=0;i<m;i++)
		{
			if(p[id].yu==0&&da[i]==0)continue;
			int yu=(p[id].yu*type+da[i])%n;
			if(done[yu])continue;
			if(yu==0)
			{
				win=1;
				showpath(id);
				if(da[i]>=10)printf("%c\n",da[i]-10+'A');
				else printf("%d\n",da[i]);
				return ;
			}
			done[yu]=1;
			p[cnt].key=da[i];
			p[cnt].yu=yu;
			p[cnt].pre=id;
			p[cnt].place=p[id].place+1;
			q.push(cnt++);
		}
	}
}
int main()
{
	int N;char c,s[3];
	//freopen("123.txt","r",stdin);
	cin>>N;
	while(N--)
	{
		scanf("%d%d%d",&n,&type,&m);
		gets(s);
		for(i=0;i<m;i++)
		{
			scanf("%c%*c",&c);
			if(c>='A'&&c<='Z')da[i]=10+c-'A';
			else da[i]=c-'0';
		}
		sort(da,da+m);
		while(da[m-1]>=type)
		{
			m--;
			if(!m)break;
		}
		if(!m){printf("give me the bomb please\n");continue;}
		if(n==0)
			if(da[0]==0){printf("0\n");continue;}
			else {printf("give me the bomb please\n");continue;}		
		bfs();
		if(!win)printf("give me the bomb please\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值