这类题目属于搜索类问题,一般可采用搜索,进行暴力求解。
输入一个自然数N(1<=N<=9),从小到大输出用1~N组成的所有排列,也就说全排列。
##代码
#include
#include
#include
using namespace std;
int n;
int visited[10]; //标记已使用过的数字
int A[10]; //存放排列好的数
int ans; //记录全排列的种数
void print_permutation(int cur)
{
if(cur==n) //边界条件
{
ans++;
for(int i=0;i<n;i++)
{
printf("%d",A[i]);
}
printf("\n");
return;
}
for(int i=1;i<=n;i++)
{
if(!visited[i]) //如果标记为0,则该数字未使用过
{
A[cur]=i;
visited[i]=1; //该数字已使用,标记为1
print_permutation(cur+1);
visited[i]=0; //很关键,一定要再次标记为0,为了进行下一次尝试
}
}
}
int main()
{
cin>>n;
print_permutation(0);
printf("%d\n",ans);
return 0;
}
输入N个自然数(1<=N<=9),从小到大输出用N个自然数组成的所有排列。例如:输入3个自然数2 6 9,输出
269
296
629
692
926
962
基于上面题解法,只需稍微改下,定义一个数组,用来存放N个自然数。
#include
#include
#include
using namespace std;
int n;
int visited[10];
int A[10],As[10];
int ans;
void print_permutation(int cur)
{
if(cur==n)
{
ans++;
for(int i=0;i<n;i++)
{
printf("%d",A[i]);
}
printf("\n");
return;
}
for(int i=0;i<n;i++)
{
if(!visited[As[i]])
{
A[cur]=As[i];
visited[As[i]]=1;
print_permutation(cur+1);
visited[As[i]]=0;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>As[i];
}
print_permutation(0);
printf("%d\n",ans);
return 0;
}
以上两种题都是对无重复元素的排列,但有时遇到有重复元素时该如何排列呢,比如对1 1 1全排列。
#include
int k=0;
void print_permutation(int n,int* p,int* A,int cur)
{
if(cur==n)//递归边界
{
++k;
for(int i=0;i<n;i++)
{
printf("%d",A[i]);
}
printf("\n");
}
else //尝试在A[cur]中填各种i
{
for(int i=0;i<n;i++)
{
if(!i||p[i]!=p[i-1])
{
int c1=0,c2=0;
for(int j=0;j<cur;j++) if(A[j]==p[i]) c1++;
for(int j=0;j<n;j++)
{
if(p[j]==p[i])
c2++;//如果i已经在A【0】~A【cur-1】中出现,则不再选
}
if(c1<c2)
{
A[cur]=p[i];
print_permutation(n,p,A,cur+1);//递归调用
}
}
}
}
}
int main()
{
int n,A[10000],cur=0,p[10000];
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&p[i]);
}
print_permutation(n,p,A,cur);
printf("%d\n",k);
return 0;
}
该题是南阳oj上的一道搜索题,这道题只需要一个限制变量即可,解法跟第一道题相同
小明十分聪明,而且十分擅长排列计算。比如给小明一个数字5,他能立刻给出1-5按字典序的全排列,如果你想为难他,在这5个数字中选出几个数字让他继续全排列,那么你就错了,他同样的很擅长。现在需要你写一个程序来验证擅长排列的小明到底对不对。
第一行输入整数N(1 在1-n中选取m个字符进行全排列,按字典序全部输出,每种排列占一行,每组数据间不需分界。 找出从自然数1、2、… 、n(0< n<10)中任取r(0< r<=n)个数的所有组合。 输入n,r 按特定顺序输出所有组合。 ##问题描述 两个十进制整数N和K。 一个十进制正整数,为包含N位数字的有效K-进制数的总数。 c++的STL中提供了一个库函数next_permutation,该函数是“求下一个排列”。那该函数该如何使用呢,还是上代码来解释吧! 类似的,有下一个排列函数,就有上一个排列函数,该函数与下一个排列函数使用方法相同,但该函数全排列前提条件自然就是数组元素从大到小排列了。就不展示该函数的代码了。 很好用的两个排列函数,学会了可以节省大量时间来编写排列递归函数,哈哈哈!输出
代码
#include
组合数
题目描述
输入
输出
特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。代码
#include
K进制数
考虑包含N位数字的K-进制数. 定义一个数有效, 如果其K-进制表示不包含两连续的0.
考虑包含N位数字的K-进制数. 定义一个数有效, 如果其K-进制表示不包含两连续的0.
给定两个数N和K, 要求计算包含N位数字的有效K-进制数的总数.(2 <= K <= 10; 2 <= N; 4 <= N+K <= 18.)
例如:
1010230 是有效的7位4进制数
注意:0001235 不是7位数, 而是4位数.输入
输出
代码
#include
下一个排列函数next_permutation
#include
上一个排列函数prev_permutation