zoukankan      html  css  js  c++  java
  • poj 1465

      题意是: 给出一个 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 20009
    using 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;
    }



  • 相关阅读:
    [SAP Rolling Out] Unit TEST/INTEGRATION TEST/UAT TEST/PARREL TESTING
    针式PKM与众不同的地方
    针式PKM拖动收集功能兼容所有的浏览器
    周九常:个人知识管理的三个重点领域
    关闭word文件老是说normal.dot被另外一人使用
    针式PKM初级应用:修改知识点的颜色评介
    寻找识货的人
    针式PKM中级应用如何将知识管理应用到新项目研发中
    针式PKM中级应用在10秒以内找到本月收集的任意文章
    针式PKM中级应用:知识点之间如何链接
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3063642.html
Copyright © 2011-2022 走看看