poj1465Multiple(经典BFS+余数判重)

Multiple
Time Limit: 1000MS   Memory Limit: 32768K
Total Submissions: 6936   Accepted: 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;
}


你可能感兴趣的:(poj1465Multiple(经典BFS+余数判重))