// 题意:
// 输入两个整数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("\n"); } 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("\n"); } 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("\n"); } 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("\n"); } 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("\n"); } } if(T) printf("\n"); } 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("\n"); } 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("\n"); } 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("\n"); }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("\n"); } return 0; }