zoukankan      html  css  js  c++  java
  • USACO / Stringsobits (DP构造/康托展开)

    Stringsobits



    [
    描述

    考虑排好序的N(N<=31)位二进制数。

    你会发现,这很有趣。因为他们是排列好的,而且包含所有可能的长度为N且含有1的个数小于等于L(L<=N)的数。

    你的任务是输出第I(1<=I<=长度为N的二进制数的个数)大的,长度为N,且含有1的个数小于等于L的那个二进制数。

    格式

    PROGRAM NAME: kimbits

    INPUT FORMAT:

    (file kimbits.in)

    共一行,用空格分开的三个整数N,L,I。

    OUTPUT FORMAT:

    (file kimbits.out)

    共一行,输出满足条件的第I大的二进制数。

    SAMPLE INPUT

    5  3  19
    

    SAMPLE OUTPUT

    10011

     

    分析:

    这道题算比较经典的DP+构造了吧~~~
     
    一开始想着暴力判断 O(logN*N),枚举N*判断每一个数1的个数logN。这种显然超时的算法下次就不要想了= =!。。。(每次想好前先给我算一下复杂度!)
     
    然后就考虑DP吧~~~
     

    先用动态规划计算:长度为I的01串,1的个数不大于j的有多少个

    其状态表示为f[i,j]

    方程:f[i,j]=f[i-1,j]+f[i-1,j-1]; //分别表示在当前位加上0和加上1时的两种状况

    边界:f[i,0]=1,f[0,i]=1;

    然后就是用字符串构造了(注:这里的K就是原题中的I)

    第一次,寻找1的最高位位置,从次高位开始扫描(i:=n-1 downto 1),看从当前位到最后,1的个数是否超过L,比较f[i,l]与K的大小。如果f[i,l]>=K这一位不为1(因为满足条

    件的前K个都是由后面i-1位01串构成的),向S加入一个‘0’补足高位;否则,找到了第一个f[i,l]<k(也就是说,仅由当前i位已经无法构成足至少k个满足条件的01串),这是

    第i+1位必须添上一个‘1’,然后dec(k,f[i,l]),dec(l)

    然后按照相同的方法继续构造接下来的‘1’,不足的全部由‘0’补足 

    PS:这个算法标准化应该就是康托展开 吧~~~O.O。。。

    代码:

     1 /*
     2 ID:138_3531
     3 LANG:C++
     4 TASK:kimbits
     5 */
     6 
     7 
     8 #include <fstream>
     9 #include <iostream>
    10 #include <cstdio>
    11 #include <cstdlib>
    12 #include <cmath>
    13 #include <iomanip>
    14 #include <climits>
    15 #include <vector>
    16 #include <set>
    17 #include <bitset>
    18 #include <map>
    19 #include <algorithm>
    20 #include <string>
    21 #include <cstring>
    22 
    23 
    24 using namespace std;
    25 
    26 
    27 int MAX(int a,int b)
    28 {
    29     return a>b?a:b;
    30 }
    31 
    32 
    33 int MIN(int a,int b)
    34 {
    35     return a>b?b:a;
    36 }
    37 
    38 
    39 ifstream fin("kimbits.in");
    40 ofstream fout("kimbits.out");
    41 
    42 
    43 int a[33];
    44 long long f[33][33];
    45 
    46 
    47 int main()
    48 {
    49     long long n,l,I;
    50     fin>>n>>l>>I;
    51 
    52 
    53     memset(f,0,sizeof(f));
    54     for (int i=0;i<=n;i++)       //initialize array f
    55     {
    56         f[0][i]=1;
    57         f[i][0]=1;
    58     }
    59 
    60 
    61     for (int i=1;i<=n;i++)          //preprocess array f
    62         for (int j=1;j<=l;j++)
    63         {
    64             f[i][j]=f[i-1][j]+f[i-1][j-1];
    65             //cout<<i<<' '<<j<<' '<<f[i][j]<<endl;
    66         }
    67 
    68 
    69     int k=l;
    70     memset(a,0,sizeof(a));
    71 
    72 
    73     for (int i=n-1;i>=0;i--)
    74     {
    75         if (f[i][k]>=I)
    76             a[i+1]=0;
    77         else
    78         {
    79             a[i+1]=1;
    80             I-=f[i][k];
    81             k--;
    82         }
    83 
    84 
    85     }
    86 
    87 
    88     for (int i=n;i>=1;i--)
    89         fout<<a[i];
    90     fout<<endl;
    91 
    92 
    93     return 0;
    94 }
  • 相关阅读:
    基础
    条件语句/变量和基本数据类型
    编程语言介绍
    asp.net中log4net使用方法
    web布到服务器上出错
    《转》IEnumerable、IEnumerator两个接口的认识
    异步ADO.NET
    Session的使用
    AJAX参数及各种HTTP状态值
    简易的抓取别人网站内容
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/2598260.html
Copyright © 2011-2022 走看看