(BFS)poj1465-Multiple

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