您的位置:首页 > 其它

hdu 4474 转化为bfs + 一个巧妙的剪枝~

2014-10-15 21:47 399 查看
比赛的时候只想到的暴力枚举的方法 枚举n的倍数 但是不确定到哪里为止输出-1。看了题解其实可以转化为, 0-9这十个数字里面的若干个数字组合出一个数,使这个数是N的倍数,求最小的这个这样的数,不存在的话输出-1。这样地话就成了一道bfs的题目,再加一个很巧妙的剪枝,可以在规定时间求出。

参考大神博客:http://blog.csdn.net/yang_7_46/article/details/12356587

优化方法:如果一个数%N==0,那么这个数就是N的倍数。在没有找到的前提下,如果A%N==B%N,而且A<B,那么其实我们就可以取A而不取B,因为如果在A末尾增加C可以使得AC%N==0,那么BC%N也等于0,易得:如果A和B追加数之后%N==0,那么最优条件下追加的数肯定相同。

参考大神代码: http://www.cnblogs.com/wally/archive/2013/03/24/2978645.html
#include<iostream>
#include<cstring>
#include<queue>
const int N=10010;
using namespace std;
int n,m;
int a[10];
int pre
,num
;

void print(int u)
{
if(pre[u]!=-1)print(pre[u]);//pre[]保存的是形成u的前一个结点,直到为-1;
printf("%d",num[u]);//由于num[]保存的记录u的最后一个数字,应此应该逆序输出
}

void bfs()
{
queue<int>Q;
for(int i=1; i<=9; i++)
if(!a[i])
{
int t=i%n;
if(t==0)
{
printf("%d",i);
return ;
}
Q.push(t);
num[t]=i;
}
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int i=0; i<=9; i++)if(!a[i])
{
int t=(u*10+i)%n;
if(num[t]==-1)
{
Q.push(t);//只存余数t
pre[t]=u;//由于记录到达t的前一个结点u;
num[t]=i;//记录形成t的最后一位数字
}
if(t==0)
{
print(t);
return ;
}
}
}
printf("-1");
}

int main()
{
int _case=1;
while(~scanf("%d%d",&n,&m))
{
memset(a,0,sizeof(a));
memset(pre,-1,sizeof(pre));
memset(num,-1,sizeof(num));
int x;
while(m--)
{
scanf("%d",&x);
a[x]=1;
}
printf("Case %d: ",_case++);
bfs();
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: