729

 

// 题意:
// 输入两个整数N, H,按照字典序输出所有长度为N,恰好包含H个1的01串
// 规模:1<=H<=N<=16
// 算法A:2^N枚举,输出1的个数为H的。采用递归枚举

// 从bits[d]开始确定,已经用了c0个0和c1个1

算法A:递归枚举

// 算法A:2^N枚举,输出1的个数为H的。采用递归枚举
#include <cstdio>
#include <cstring>
const int maxn = 20;
int N, H, bits[maxn];

// 从bits[d]开始确定,已经用了c0个0和c1个1
void gen(int d, int c0, int c1) {
  if(d == N) {
    if(c1 != H) return;
    for(int i = 0; i < N; i++) printf("%d", bits[i]);
    printf("
");
  } else {
     bits[d] = 0; gen(d+1, c0+1, c1);
     bits[d] = 1; gen(d+1, c0, c1+1);
  }
}

int main() {
  int T;
  scanf("%d", &T);
  while(T--) {
    scanf("%d%d", &N, &H);
    gen(0, 0, 0);
    if(T) printf("
");
  }
  return 0;
}

 

算法A改进:递归枚举加剪枝

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int n,h;
int buf[16];
void solve(int c0, int c1, int d)
{
    if(d==n)
    {
        if(c1==h)
        {
            for(int i=0;i<n;i++)
                printf("%d", buf[i]);
            printf("
");
        }
        return;
    }

    if(c0<n-h)
    {
        buf[d]=0;
        solve(c0+1, c1, d+1);
    }

    if(c1<h)
    {
        buf[d]=1;
        solve(c0, c1+1, d+1);
    }

}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &h);
        solve(0, 0, 0);
        if(T)
            printf("
");
    }

    return 0;
}

 

算法B:二进制枚举子集

// 算法B:2^N枚举,输出1的个数为H的,采用直接枚举子集
#include <cstdio>
#include <cstring>
int N, H;

int main() {
  int T;
  scanf("%d", &T);
  while(T--) {
    scanf("%d%d", &N, &H);
    for(int i = 0; i < (1<<N); i++) {
      int cnt = 0;
      for(int j = 0; j < N; j++) if(i & (1<<j)) cnt++;
      if(cnt == H) {
        for(int j = N-1; j >= 0; j--) printf("%d", (i & (1<<j)) ? 1 : 0);
        printf("
");
      }
    }
    if(T) printf("
");
  }
  return 0;
}

算法C:

// 算法C:C(N,H)枚举,枚举的对象为0,所以枚举顺序就是字典序
#include <cstdio>
#include <cstring>
const int maxn = 20;
int N, H, zero[maxn]; // zero[i]为第i为是否为0

// 从第d个0的位置开始确定,取值范围是from~N-1
void gen(int d, int from) {
  if(d == N-H) {
    for(int i = 0; i < N; i++) printf("%d", zero[i] ? 0 : 1);
    printf("
");
  } else {
     for(int i = from; i < N; i++) {
       zero[i] = 1;
       gen(d+1, i+1);
       zero[i] = 0;
     }
  }
}

int main() {
  int T;
  scanf("%d", &T);
  while(T--) {
    scanf("%d%d", &N, &H);
    memset(zero, 0, sizeof(zero));
    gen(0, 0);
    if(T) printf("
");
  }
  return 0;
}

算法D: stl next_permutation

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

const int N=100;
int s[N];
int n, r;

void rcom()
{
    do
    {
        for(int i=0;i<n;i++)
        {
            printf("%d", s[N-n+i]);    
        }
        printf("
");
    }while(next_permutation(s+N-n, s+N));
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>r;
        memset(s, 0, sizeof s);
        for(int i=0;i<r;i++)
        {
            s[N-1-i]=1;    
        }
        rcom();
        if(T)
            printf("
");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/cute/p/3696808.html