青藤oj #10049. 全排列问题
题目描述
输出自然数 1 到n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
n(1≤n<9)
输出格式
由 1~n 组成的所有不重复的数字序列,每行一个序列。注意,每个数前面输出4个空格,包括第一个数。
思路
用递归每一个数都试一遍,如果没用过就标记为1,如果用过就下一个;
用s存下每一深度记下的数,当深度大于位数时,输出s;
return,从上一步继续往下推;
代码
#include<bits/stdc++.h>
using namespace std;
int a[1000]={0},s[1000];
int n;
void dfs(int deep)
{
if(deep==n+1)
{
for(int i=1;i<=n;i++)
cout<<" "<<s[i];
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
if(a[i]==1)
continue;
a[i]=1;
s[deep]=i;
dfs(deep+1);
a[i]=0;
}
return;
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
青藤oj #10277. 组合的输出
题目描述
排列与组合是常用的数学方法,其中组合就是从 n个元素中抽出 r个元素(不分顺序且 r<=n),我们可以简单地将n 个元素理解为自然数1 ,2 ,… ,n ,从中任取 r个数。现要求你用递归的方法输出所有组合。
输入格式
一行两个自然数n 、r (1<n<21 ,1<=r<=n )
输出格式
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素前面包含一个空格(包括第一个元素)
思路
这题和上一题差不多,就是要考虑一个重复的问题;
我的方法是在每一次循环结束后,也就是这一深度每个数都试过后,就将上一深度+1到n之间的数归0,重新枚举;
代码
#include<bits/stdc++.h>
using namespace std;
int s[10000],ans[10000];
int n,r,x;
void dfs(int deep)
{
if(deep==r+1)
{
for(int i=1;i<=r;i++)
cout<<" "<<ans[i];
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
int x=i;
if(s[i]==1)
continue;
s[i]=1;
ans[deep]=i;
dfs(deep+1);
}
for(int i=ans[deep-1]+1;i<=n;i++)
s[i]=0;
}
int main()
{
cin>>n>>r;
dfs(1);
}
青藤oj #10119. 自然数和分解
题目描述
把自然数N分解为若干个大于 0 自然数之和,输出方案数。
输入格式
N,(1≤n≤50)
输出格式
方案数
思路
用x累计,每次都判断是否等于n;如果等于就s+1,return;
如果没到n那就从r(上一次循环所加的数)开始往下枚举;
如果x加上i小于或等于n的,x就加上i,将i赋值给r(下一层枚举时用);
循环完以后,减掉r(i也行);
最后输出s;
代码
#include<bits/stdc++.h>
using namespace std;
int n,s=0,x=0;
void dfs(int r)
{
if(x==n)
{
s++;
return;
}
for(int i=r;i>=1;i--)
{
if(x+i>n) continue;
x+=i;
r=i;
dfs(r);
x-=r;
}
return;
}
int main()
{
cin>>n;
dfs(n);
cout<<s;
}
青藤oj #160. 数的划分
题目描述
将整数n 分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。
例如:n=7,k=3下面三种分法被认为是相同的。
1,1,5; 1,5,1; 5,1,1;
问有多少种不同的分法。
输入格式
输入 n和k .
输出格式
方案数
思路
和上题相似,只是在s++时多判断一个条件,长度是否达到k;
(一开始超时,还加了快读快些。后来才知道是因为当deep>k+1,x<n时,还在继续递归,加上判断就好了)
代码
#include<bits/stdc++.h>
using namespace std;
int n,s=0,x=0,k;
inline int read()
{
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
inline void write(int x)
{
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
void dfs(int r,int deep)
{
if(x==n&&deep==k+1)
{
s++;
return;
}
if(deep==k+1) return ;
for(int i=r;i>=1;i--)
{
if(x+i>n) continue;
x+=i;
r=i;
dfs(r,deep+1);
x-=r;
}
return;
}
int main()
{
n=read();
k=read();
dfs(n,1);
write(s);
}
青藤oj
题目描述
输入格式
输出格式
思路
代码
这篇博客详细介绍了如何使用递归算法解决全排列、组合等数学问题,包括青藤oj上的多个题目,如全排列问题(#10049)、组合输出(#10277)、自然数和分解(#10119)以及数的划分问题(#160)。通过递归思路,博主阐述了解决这些问题的关键步骤,并提供了相应的代码实现。

1160

被折叠的 条评论
为什么被折叠?



