hdu 4474 Yet Another Multiple Problem bfs

题意:输入n和m,接着输入m个十进制的数字,求最小的数ans,使得ans是n的倍数(除了0),且ans中不包括输入的十进制数字。不存在输出-1.

题解:这是一道广搜题,先找出所有可以组合ans的数字,然后就是按位枚举所有的组合(从长度为1的开始)。需要用同余剪枝,若a<b&&a%n==b%n,则之后枚举的是a=10*a+i和b=10*b+i,余数必定相同,且a<b。当出现a%n=0,b%n=0时,ans=a。所以用vis数组标记余数进行剪枝,单次复杂度最坏也只是n次。之后结果可能很大,所以不能直接用int来存,可以建个前驱标志用于输出,也可以建int数组(不过,应该不够吧),我是用string来存的。


耗时:3000MS/20000MS

#include <cstdio>
#include <cstring>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1e4+10;
int vis[maxn];
int c[11];
int n,m;
string str[11]={"0","1","2","3","4","5","6","7","8","9"};
struct node{
    int a;
    string s;
 };
queue<node>q;
void bfs()
{
    while(!q.empty())q.pop();
    memset(vis,0,sizeof(vis));
    int i,j,k,p;
    node e,u,v;
    for(i=1;i<=9;i++)if(!c[i]){
        if(vis[i%n])continue;
        vis[i%n]=1;
        e.a=i%n;
        e.s=str[i];
        q.push(e);
    }
    while(!q.empty())
    {
        e=q.front();
        if(e.a==0)break;//这里放pop()前,不然e是队列中的最后一个就要倒霉了。。
        q.pop();
        for(i=0;i<=9;i++)if(!c[i]){
            p=(e.a*10+i)%n;
            if(vis[p])continue;
            vis[p]=1;
            u.a=p;
            u.s=e.s+str[i];
            q.push(u);
        }
    }
    if(!q.empty())
    {
        cout<<e.s<<endl;
    }
    else
    printf("-1\n");
}
int main()
{
    int tt=0;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int i,j,k,a;
        memset(c,0,sizeof(c));
        for(i=0;i<m;i++)
        {
            scanf("%d",&a);
            c[a]++;//可能重复哦。。
        }
        printf("Case %d: ",++tt);
        bfs();
    }
    return 0;
}


你可能感兴趣的:(hdu 4474 Yet Another Multiple Problem bfs)