首页 > 代码库 > (BFS)poj1465-Multiple

(BFS)poj1465-Multiple

题目地址

题意可理解为我们有一些给定的元素,要用它们组成数,如果一个长度(x)所有组成的数都不是给定的另一个数(n)的倍数,并且长度为x的数中有模n的不同于长度小于x的数模n的数,那么继续延长这个数的长度。这样进行到无法进行下去时,就是要输出0的情况,中途如果找到了n的倍数,就直接返回输出。题目比较关键的是我们只需关注模n意义下的情况,这样就省略了很多细枝末节没有影响的数,并且有效的控制了数的大小,使之在我们可以接受的范围内。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,digit[10],an;//digit数组用于储存题目中可以出现的数(因为都是个位数,所以大小设为10)
struct node
{
    int yu;//这个数模n的余数
    int digit;//这位的数码
    int pre;//这一位前一位的数
}q[5052];//建立一个结构体,方便操作
bool flag[5052];//通过bool数组记录某一个余数是否出现过
int bfs()
{
    memset(flag,0,sizeof(flag));
    int front=0,tail=1;
    q[front].yu=0;
    q[front].pre=-1;//将第一个的pre初始化为不可能取得的数,进行后面的判断
    q[front].digit=0;
    while(front<tail)//继续进行的条件
    {
        node p=q[front];
        int r=p.yu;//之前的余数
        for(int i=0;i<m;i++)
        {
            int nr=(10*r+digit[i])%n;//新的余数
            if(!flag[nr]&&(p.pre!=-1||digit[i]!=0))//如果没有出现过这个余数,并且满足不是第一位或这一位是0条件之一(因为往后不可以出现0,只是加0不改变余数)
            {
                flag[nr]=true;
                p.pre=front;
                p.digit=digit[i];
                p.yu=nr;
                q[tail++]=p;
                if(nr==0)
                    return tail-1;
            }
        }
        front++;
    }
    return -1;
}
void print(int x)//比较巧妙的输出方式,学习了
{
    if(x>0)
    {
        print(q[x].pre);
        printf("%d",q[x].digit);
    }
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        scanf("%d",&m);
        for(int i=0;i<m;i++)
            scanf("%d",&digit[i]);
        if(n==0)//0要单独讨论一下
        {printf("0\n");
        continue;}
        sort(digit,digit+m);
        int an=bfs();
        if(an==-1)
            printf("0\n");
        else
            {print(an);
            puts("");}
    }
    return 0;
}

 

(BFS)poj1465-Multiple