您的位置:首页 > 其它

zoj 1136(同余+bfs)

2014-08-14 11:24 295 查看
题意:求用m个数字(0-9)组成的n的倍数最小的那个。

分析:bfs从前往后搜索每位数字的情况,还用到了同余定理剪枝,举个例子,n=12时,搜索到13,加入队列,接着在后面又搜到25,请注意,25%12==13%12,假如25也要加入队列的话,当两数在后面加上相同数字,余数将一直相同,254%12==134%12,知道这一点,接下来,当25*****%12==13*****%12==0时,取最小13的串,也就是说25的结果一定不如13更优,干脆不搜,直接剪掉。做法:done[]存余数的出现情况(是否出现过)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN=25;
int done[5005],n,m;
int da[13];

struct node
{
    int key,pre,yu;
    node(int k=0,int y=0,int p=0)
    {
        key=k;pre=p;yu=y;
    }
}q[10000];
void showpath(int id)
{
    if(q[id].pre==-1)return ;
    showpath(q[id].pre);
    printf("%d",q[id].key);
}

bool bfs()
{
    memset(done,0,sizeof done);
    int st=0,en=0;
    q[en++]=node(0,0,-1);
    while(st<en)
    {
        node x=q[st++];
        for(int i=0;i<m;i++)
        {
            if(x.yu==0&&da[i]==0)continue;//第一个加入队列的0需要处理
            int curyu=(x.yu*10+da[i])%n;
            if(done[curyu])continue;//剪掉余数相同的
            if(curyu==0)
            {
                showpath(st-1);
                printf("%d\n",da[i]);
                return 1;
            }
            done[curyu]=1;
            q[en++]=node(da[i],curyu,st-1);
        }
    }
    return 0;
}

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