指数型枚举:
题目描述:
从1~n这n个整数中随机选取任意多个,每种方案里的数从小到大排列,按字典序输出所有可能的选择方案。
输入:
输入一个整数 n (1≤n≤10)
输出:
每行一组方案,每组方案中两个数之间用空格分隔。
注意每行最后一个数后没有空格。
输入样例:
4
输出样例:
1
1 2
1 2 3
1 2 3 4
1 2 4
1 3
1 3 4
1 4
2
2 3
2 3 4
2 4
3
3 4
4
题解:
按位枚举即可,设枚举的位数是 i,该位最小可枚举的是 j,该位枚举到 n 为止
我们需要一个数组来存放每位的数据。一开始我没开数组,结果写了半天hh
所以我们需要设计的函数有 4 个参数,f(int i, int j, int n, int* pa)
每位的数字,每次枚举完都需要输出,可以将此单独写成一个函数,print_ans(int i, int* pa)
每次枚举完枚举下一位,递归,直到 n 结束
代码:
#include <stdio.h>
void print_ans(int i, int* pa)
{
int k;
for (k = 0; k < i; k++)
{
printf("%d", pa[k]);
if (k < i - 1)//注意题目要求,最后不能有空格
printf(" ");
}
printf("\n");
}
void f(int i, int j, int n, int* pa)
{
int k;
for (k = j; k <= n; k++)//枚举j~n,按这样的顺序就是字典序了
{
pa[i - 1] = k;
print_ans(i, pa);//每次枚举完输出
if (k < n)//到k为止,否则继续递归
f(i + 1, k + 1, n, pa);
}
}
int main()
{
int n, a[10] = { 0 };
scanf("%d", &n);
f(1, 1, n, a);//从第1位、1开始
return 0;
}
组合型枚举:
题目描述:
从 1−n 这 n 个整数中随机选取 m 个,每种方案里的数从小到大排列,按字典序输出所有可能的选择方案。
输入:
输入两个整数 n,m。(1≤m≤n≤10)
输出:
每行一组方案,每组方案中两个数之间用空格分隔。
注意每行最后一个数后没有空格。
输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
题解:
跟指数型枚举差不多。其实我们只要在指数型枚举的基础上
引入变量 l,写在参数里,每次输出前加一个判断 if(i == l) 就行了
还能再优化一下,i >= l 便不再递归
代码:
#include <stdio.h>
void print_ans(int i, int* pa)
{
int k;
for (k = 0; k < i; k++)
{
printf("%d", pa[k]);
if (k < i - 1)
printf(" ");
}
printf("\n");
}
void f(int i, int j, int n, int l, int* pa)
{
int k;
for (k = j; k <= n; k++)
{
pa[i - 1] = k;
if(i == l)//引入变量l,符合该条件再输出就行了
print_ans(i, pa);
if (k < n && i < l)//递归条件还可以优化,加一条 i < l,减少递归次数
f(i + 1, k + 1, n, l, pa);
}
}
int main()
{
int n, l, a[10] = { 0 };
scanf("%d%d", &n, &l);
f(1, 1, n, l, a);
return 0;
}
排列型枚举:
题目描述:
从 1−n 这 n 个整数排成一排并打乱次序,按字典序输出所有可能的选择方案。
输入:
输入一个整数 n。(1≤n≤8)
输出:
每行一组方案,每组方案中两个数之间用空格分隔。
注意每行最后一个数后没有空格。
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
题解:
跟前两个也差不多
因为不要求后一个数大于前一个数,所以不再需要 j
用数组 b[10] 取而代之,引入它来表示各数字是否已被使用,b[m]表示m+1
使用过的数字就标记,返回后解除标记
代码:
#include <stdio.h>
void print_ans(int i, int* pa)
{
int k;
for (k = 0; k < i; k++)
{
printf("%d", pa[k]);
if (k < i - 1)
printf(" ");
}
printf("\n");
}
void f(int i, int n, int* pa, int* pb)
{
int k;
for (k = 1; k <= n; k++)
{
if (!pb[k - 1])
{
pb[k - 1] = 1;//标记被使用过的数字
pa[i - 1] = k;
if (i == n)
print_ans(i, pa);
if (k <= n && i < n)
f(i + 1, n, pa, pb);
pb[k - 1] = 0;//返回后解除标记
}
}
}
int main()
{
int n, a[10] = { 0 }, b[10] = { 0 };
scanf("%d", &n);
f(1, n, a, b);
return 0;
}