poj 1465

来源:互联网 发布:苍の骑士团日服数据库 编辑:程序博客网 时间:2024/06/10 20:14

  题意是: 给出一个 0 - 4999 的数 N  ,在给出 M 个0-9的数,判断这M个数字能不能构成一个数是N的倍数,如果有输出最小的,如果没有输出0。

此题用BFS 。。 这个题好在 用 余数判重剪枝。。 

BFS  如果不加以剪枝,一定会搜索的情况会很庞大。所以应该用余数判重 。

   为什么可以用余数判重?

       A=a*N +e 即A%N =e

       B= b*N+e即B%N=e

      当A  B mod N的余数相同时,如果先出现A 。

      在A  后加上一个数 i 时 ,  新的数   C = 10 *a*N + 10 *e+i;

      同样  B后加上数 i 时 , D = 10*b*N +10*e+i;    由于C D 前边 10*a*N 和 10*b*N 都是N的倍数 ,则C D mod N 的余数都是有 10*e+i 决定的。

    于是 C D  mod N 同余。

    因此 A B 同余 都添加上 i 之后 新的两个数C D也是同余的。在无论添加多少个数,新生成的两个数也是同余的。因此 在A 之后如果不出现 N的倍数 ,则

在B之后也不会出现。 在A 之后出现,那B之后也会出现。  有因为要求求最小值。所以只需要搜索min(A,B)之后的 ,对于另外一个数之后就不用搜索了。

#include<cstdlib>#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<set>#include<map>#include<list>#include<queue>#include<vector>#define LL long long#define inf 0x7fffffff#define eps 1e-7#define N 5509#define M 20009using namespace std;int T,n,m,k;struct Node{    LL v;    int w;    int pre;} a[N];int h[100];int vis[N];void print(int x){    if(x)    {        print(a[x].pre);        printf("%d",a[x].w);    }}void bfs(){    int l=0,r=1;    a[0].pre=a[0].w=a[0].v=0;    while(l<r)    {        Node t;        t=a[l];        t.pre=l++;        int v=t.v;        for (int i=0; i<m; ++i )        {            int x=(v*10+h[i])%n;//n不能是0,Float-Point Error            if(x==0&&l!=1)            {                print(t.pre);                printf("%d\n",h[i]);                return ;            }            if(vis[x]||(l==1&&h[i]==0))continue;            vis[x]=1;            t.v=x;            t.w=h[i];            a[r++]=t;        }    }    printf("0\n");}int main(){#ifndef ONLINE_JUDGE    freopen("ex.in","r",stdin);#endif    int ncase=0;    while (scanf("%d%d",&n,&m)==2)    {        memset(vis,0,sizeof(vis));        for(int i=0; i<m; ++i)        {            scanf("%d",&h[i]);        }        if (n==0)//        {            printf("0\n");            continue;        }        sort(h,h+m);        bfs();    }    return 0;}


原创粉丝点击