poj 1426 Find The Multiple (dfs)

本文介绍了解决POJ 1426问题的几种方法,包括使用结构体加优先队列尝试但内存不足、直接枚举01序列导致超时,最终采用深度优先搜索替换部分0为1的技巧性枚举方法成功解决。提供了AC代码及两种错误示例代码供参考。

http://poj.org/problem?id=1426

(1)用了结构体加上优先队列:

struct node
{
    int n, v, digit;
    node *pre;
}

  注意到深度为100,内存不足。。(字典树深度为10,深度没有这么大)。

(2)从小到大枚举01序列,超时。

(3)深搜,将部分的0替换成1,可以认为是一种技巧性的枚举,AC。

具体代码:

View Code
#include<stdio.h>
#include<string.h>
int m, flag;
int re[120];
int yes()
{
    int i, c=0;
    for(i=1;i<=100;i++)
    {
        c*=10; c+=re[i];
        c%=m;
    }
    if(c) return 0;
    return 1;
}
void put()
{
    int i;
    for(i=1;i<=100;i++)
        printf("%d", re[i]);
    printf("\n");
}
void dfs(int x)
{
    int i;
    if(flag) return ;
    if(yes()) {put(); flag=1; return ;}
    for(i=x;i<=100;i++)
    {
        if(re[i]) continue;
        re[i]=1;
        dfs(i+1);
        if(flag) return ;
        re[i]=0;
    }
}
int main()
{
    while(scanf("%d", &m)!=EOF, m)
    {
        memset(re, 0, sizeof(re));
        re[1]=1;
        flag=0;
        dfs(2);
    }
    return 0;
}

这里附上两种错误的代码,予以警示。

1)超内存代码:

View Code
#include<stdio.h>
#include<string.h>
int m;
struct node
{
    int n, v, digit;
    node *pre;
}q[1000000], e, s;
int tot, re[200];
int bfs()
{
    int i, j, k;
    int start, tail;
    start=tail=0;
    e.n=1, e.v=1, e.digit=1, e.pre=NULL;
    q[tail]=e;
    while(start<=tail)
    {
        e=q[start++];
        if(e.n==0) break;
        for(i=0;i<2;i++)
        {
            s.n=e.n*10+i;
            s.n%=m;
            s.v=i;
            s.digit=e.digit+1;
            s.pre=&q[start-1];
            q[++tail]=s;
        }
    }
    tot=0;
    while(e.pre!=NULL)
    {
        re[tot++]=e.pre->v;
        e.pre=e.pre->pre;
    }
    for(i=tot-1;i>=0;i--)
        printf("%d", re[i]);
    printf("%d\n", e.v);
}
int main()
{
    while(scanf("%d", &m)!=EOF, m)
    {
        bfs();
    }
}

2)超时代码:

View Code
#include<stdio.h>
#include<string.h>
int m, a[120];
int yes()
{
    int i, s=0;
    for(i=100;i>=1;i--)
    {
        s*=10; s+=a[i]; s%=m;
    }
    if(s) return 0;
    else return 1;
}
int main()
{
    int i, j;
    while(scanf("%d", &m)!=EOF, m)
    {
        memset(a, 0, sizeof(a));
        a[1]=1;
        while(1)
        {
            for(i=1;i<=100;i++)
            if(!a[i])
            {
                a[i]=1;
                for(j=1;j<i;j++) a[j]=0;
                break;
            }
            if(yes()) break;
        }
        for(i=100;i>=1;i--)
            if(a[i]) break;
        for(;i>=1;i--)
            printf("%d", a[i]);
        printf("\n");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/tim11/archive/2012/08/19/2646332.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值