• poj2956 Repeatless Numbers(枚举|BFS)


    题目链接

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

    题意

    如果一个数中的每一位都是不同的,那么这个数叫做无重复数,如11是有重复数,12是无重复数。输入正整数n(1<=n<=1000000),输出第n个无重复数。

    思路

    可以使用两种方法来解决本题:枚举和bfs。

    方法一:枚举

    如果直接暴力枚举的话会超时,所以要考虑一些情况来减少枚举。比如对于一个数128267来讲,它的第2位(从右往左数)和第4位是相同的,则形如1282**的数都不用枚举了,直接从128300枚举即可,这样可加快枚举的时间。

    枚举代码:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 const int N = 1000000;
     7 int ans[N+1] = {0};
     8 int power[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
     9 
    10 void init()
    11 {
    12     int d[10];  //存储数字x
    13     int v[10];  //v[i]表示数字i是否在x中出现过
    14     int cur = 1;
    15     int x, y=1;
    16     while(cur<=N)
    17     {
    18         x = y;
    19         memset(v, -1, sizeof(v));
    20         memset(d, 0, sizeof(d));
    21 
    22         int i, j;
    23         for(i=0; x!=0; i++)
    24         {
    25             d[i] = x % 10;
    26             if(v[d[i]]!=-1)
    27                 break;
    28             v[d[i]] = i;
    29             x /= 10;
    30         }
    31         if(!x)
    32         {
    33             ans[cur++] = y;
    34             y++;
    35         }
    36         else
    37         {
    38             j = v[d[i]];
    39             for(i--; i>=j; i--)
    40                 x = x*10+d[i];
    41             x++;
    42             y = x*power[j];
    43         }
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     init();
    50     int n;
    51     while(cin>>n && n)
    52         cout<<ans[n]<<endl;
    53     return 0;
    54 }

    方法二:BFS

    bfs的初始状态为1~9,在初始状态的后面不断地添加0~9可以得到下一层状态,在对第二层状态不断地进行扩展,知道扩展到第1000000个状态为止。每一个状态包含两个属性value和digit,value为状态的值,假设为134,则digit为11010,d[i]=1表示i在value中,在数字134后添加0~9中的数字时(假设添加的数字为1),如何判断1是否在134中出现过呢,value=1,则digit = 10 ,将11010与10做与操作即11010&10,若结果不等于0,这说明1在134中存在,否则不存在。

    BFS代码

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 const int N = 1000000;
     7 struct Number
     8 {
     9     int value;  //数字的十进制表示
    10     int digit;  //二进制序列,从右往左数digit[i]==1表示value中有i
    11 
    12     Number(){}
    13     Number(int v, int d):value(v), digit(d){}
    14 }ans[N+10];
    15 
    16 int main()
    17 {
    18     for(int i=1; i<10; i++)
    19         ans[i] = Number(i, 1<<i);
    20 
    21     int k = 1;
    22     for(int cur=10; cur<=N; k++)
    23     {
    24         int v = ans[k].value;
    25         int d = ans[k].digit;
    26 
    27         for(int i=0; i<10; i++)
    28         {
    29             if( !(d & (1<<i)))
    30                 ans[cur++] = Number(v*10+i, d|1<<i);
    31         }
    32     }
    33 
    34     int n;
    35     while(scanf("%d", &n)==1 && n)
    36         printf("%d
    ", ans[n].value);
    37     return 0;
    38 }

    一点总结

    如何判断数a和数b中是否存在相同的数字呢?

    一种做法是将数a和数b的每一位分别分解到数组A[]和数组B[]中,然后遍历数组A[]、B[],试着找出相同的位。

    第二种做法是用A[i]=1表示i存在a中,A[i]=0,表示a中没有i,则对处理后的A[]和B[]进行与(&)操作,结果为0说明a,b中没有相同的位,结果为1则说明a,b中有相同的位。在上面的bfs中,如果每一个状态都存储一个数组的话,会消耗大量内存,所以可以将数组中的二进制序列转化成一个十进制整数,通过左移i位来表示数字中包含i。

    参考

    http://www.acmsearch.com/article/show/24772

  • 相关阅读:
    js检测对象是否是数组的三种方法
    mongdb查询数据并且返回数据条数
    mongdb数据库的操作
    NodeJs运行服务器-day01
    html5新增的定时器requestAnimationFrame
    vue 中scroll事件不触发问题
    Node.js快速生成26个字母
    Node.js fs文件系统模块
    Node.js 创建server服务器
    JavaScript exec()方法
  • 原文地址:https://www.cnblogs.com/sench/p/7827374.html
Copyright © 2020-2023  润新知