您的位置:首页 > 其它

poj1465Multiple(经典BFS+余数判重)

2016-05-10 15:31 127 查看
Multiple

Time Limit: 1000MSMemory Limit: 32768K
Total Submissions: 6936Accepted: 1495
Description

a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the smallest strictly positive multiple of N that has no other digits besides X1,X2..XM (if such a multiple exists).
Input

The input has several data sets separated by an empty line, each data set having the following format:

On the first line - the number N

On the second line - the number M

On the following M lines - the digits X1,X2..XM.
Output

For each data set, the program should write to standard output on a single line the multiple, if such a multiple exists, and 0 otherwise.

An example of input and output:
Sample Input
22
3
7
0
1

2
1
1

Sample Output
110
0

Source
Southeastern Europe 2000

这道题由于数据的规模,在优化上有一个很好的剪枝,会节省下不少内存和时间,就是余数判重,这个优化在别人的题解里肯定说的很多我就不再多嘴了,其次再说这个BFS,在宽搜之前要对m个数从小到大排一下序,因为题目要求是要最小的倍数,这样你要确定当你向上找到那个父节点的时候,他比之后的数都是小的-
-
最后,把得到的答案放在数组里,因为你是从最小的地方开始放的,所以输出的时候从低位到高位,要倒序输出

<( ̄ˇ ̄)/我要好好做题,好好写题解^_^

这是代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int num[12];
int n,m;
int flag[5200];
char answer[5200];
struct node{
int fid;
int num;
int mod;
}tree[5200];

queue<int>qq;

void bfs(){
if(!n){
cout<<0<<endl;
return;
}
int idx=1;
while(!qq.empty()) qq.pop();
memset(flag,0,sizeof(flag));
for(int i=1;i<=m;++i){
int nm=num[i];
int mod=nm%n;
if(!num[i]){        //若当前这个数是0,跳过
continue;
}
if(!mod){      //若当前这个数对n取余为0,说明这个数是n的倍数,直接输出这个数然后返回
cout<<nm<<endl;
return;
}
if(!flag[mod]){          //若这个数对n取余的余数以前没有取到过(余数判重) 将这个数加入到树中,将这个数的位置进入队列
flag[mod]=1;
tree[idx].fid=0;
tree[idx].num=nm;
tree[idx].mod=mod;
qq.push(idx++);
}
}

while(!qq.empty())       //广搜
{
int ff=qq.front();
qq.pop();
int md=tree[ff].mod;
for(int i=1;i<=m;++i)
{
int nm=num[i];
int addnum=md*10+nm;
int addmod=addnum%n;

if(!addmod){        //如果这个数和m个数中的一个组合是n的倍数
int k=0;
answer[k++]=nm+'0';
answer[k++]=tree[ff].num+'0';
while(tree[ff].fid)      //寻找此点的父节点
{
ff=tree[ff].fid;
answer[k++]=tree[ff].num+'0';
}
for(int kk=k-1;kk>=0;kk--)
printf("%c",answer[kk]);
printf("\n");
return;
}
if(!flag[addmod])        //如果当前次的数的组合的余数不为零且未出现过,加入队列
{
flag[addmod]=1;
tree[idx].fid=ff;
tree[idx].num=nm;
tree[idx].mod=addmod;
qq.push(idx++);
}
}
}
cout<<0<<endl;
return;
}

int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=m;++i)
scanf("%d",&num[i]);
sort(num+1,num+m+1);
bfs();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: