递归实现指数型枚举
思路分析
一共n位数字和n个位置,每个位置上每个数字都有选与不选两种情况,建成一颗递归树递归遍历输出每一种情况的答案。
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n;
int a[N];
void dfs(int x){
if(x>n){
for(int i=1;i<=n;i++){
if(a[i]) printf("%d ",i);
}
printf("\n");
}
else{
a[x]=1; //表示选择该数字
dfs(x+1); //递归到下一个位置
a[x]=0; //表示不选择该数字
dfs(x+1); //递归到下一个位置
}
}
int main(){
cin>>n;
dfs(1);
return 0;li
}
递归实现排列型枚举
思路分析
额外开辟一个新的vis数组,表示每个数字是否被使用,遍历每个位置,选择未被使用的数字放置在该位置上,并标记该数字已被使用,递归遍历下一位,特别注意“恢复现场”
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int a[N],vis[N];
int n;
void dfs(int x){
if(x>n){
for(int i=1;i<=n;i++){
printf("%d ",a[i]);
}
printf("\n");
}else{
for(int i=1;i<=n;i++){
if(!vis[i]){
a[x]=i; //该数字未被使用,放置在该位置
vis[i]=1; //表示该数字已被使用
dfs(x+1); //递归遍历下一位
vis[i]=0; //恢复现场
}
}
}
}
int main(){
cin>>n;
dfs(1);
return 0;
}
递归实现组合型枚举
思路分析
类似于实现排列型枚举,但不同的是需要选择m个数字,并且出现顺序不同的算成同种方案。
#include<bits/stdc++.h>
using namespace std;
const int N=30;
int a[N],vis[N];
int n,m;
void dfs(int x){
if(x>m){
for(int i=1;i<=m;i++){
printf("%d ",a[i]); //此时要选择m个数字
}
printf("\n");
return;
}
else{
for(int i=a[x-1]+1;i<=n;i++){
//每次遍历的开始是上一次被选择的数字后边的一个数保证不出现重复
if(!vis[i]){
a[x]=i;
vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
}
}
int main(){
cin>>n>>m;
dfs(1);
return 0;
}
带分数
思路分析
要求n=a+
c
b
\frac{c}{b}
bc,即得到nb==ab+c,实现1-9的全排列,从中截断出a,b,c三个整数,对于符合条件的整数cnt++递归结束得到正确答案。
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int t[N],vis[N];
int n,cnt;
int num(int l,int r){
// 将数组中的数字合并成一个大整数
int sum=0;
for(int i=l;i<=r;i++){
sum+=t[i];
if(i!=r) sum*=10;
}
return sum;
}
void dfs(int x){
int a,b,c;
if(x==10){
for(int i=1;i<=9;i++){
for(int j=i+1;j<=9;j++){
a=num(1,i);
b=num(i+1,j);
c=num(j+1,9);
if(n*b*1ll==a*b*1ll+c&&a&&b&&c) cnt++;
}
}
return;
}else{
for(int i=1;i<=9;i++){
// 实现全排列
if(!vis[i]){
t[x]=i;
vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
}
}
int main(){
cin>>n;
dfs(1);
printf("%d",cnt);
return 0;
}
思路2
递归遍历a,b计算出c,再对c进行判断,看c是否符合条件
#include<bits/stdc++.h>
using namespace std;
int n;
int a[10],vis[10],backup[10];
int cnt;
bool check(int a,int c){
long long b=n*(long long)c-a*c;
if (!a || !b || !c) return false;
memcpy(backup,vis,sizeof vis);
while(b){
int x=b%10;
b/=10;
if(!x||backup[x]==1) return false;
backup[x]=1;
}
for(int i=1;i<=9;i++){
if(!backup[i]) return false;
}
return true;
}
void dfs_c(int x,int a,int c){
if(x>9){
return;
}
if(check(a,c)) cnt++;
for(int i=1;i<=9;i++){
if(!vis[i]){
vis[i]=1;
dfs_c(x+1,a,c*10+i);
vis[i]=0;
}
}
}
void dfs_a(int x,int a){
if(a>=n) return;//a大于等于n时,属于无解的情况
if(a) dfs_c(x,a,0);
for(int i=1;i<=9;i++){
if(!vis[i]){
vis[i]=1;
dfs_a(x+1,a*10+i);
vis[i]=0;
}
}
}
int main(){
cin>>n;
dfs_a(1,0);
printf("%d",cnt);
return 0;
}
三连击(升级版)
思路分析
找出1-9的全排列,分割成三个数字,输出符合条件的组合。
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int a[N],vis[N];
int A,B,C;
int cnt;
void dfs(int x){
if(x==10){
int num1=a[1]*100+a[2]*10+a[3];
int num2=a[4]*100+a[5]*10+a[6];
int num3=a[7]*100+a[8]*10+a[9];
if(num1*B*C==num2*A*C&&num1*B*C==num3*A*B&&num2*A*C==num3*A*B){
cnt++;
printf("%d %d %d\n",num1,num2,num3);
}
return;
}
else{
for(int i=1;i<=9;i++){
if(!vis[i]){
a[x]=i;
vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
}
}
int main(){
cin>>A>>B>>C;
dfs(1);
if(!cnt) printf("No!!!\n");
return 0;
}
思路二
根据题意 num1BC== num2AC == num3AB
因此,可以根据等式先计算出num3,遍历枚举num1和num2找出符合条件的组合。
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int vis[N],backup[N];
int A,B,C;
int cnt;
bool check(int num1,int num2){
int num3=num1*C/A;
memcpy(backup,vis,sizeof vis);
if(num1*B*C!=num2*A*C) return false;
while(num3){
int x=num3%10;
num3/=10;
if(!x||backup[x]) return false;
backup[x]=1;
}
for(int i=1;i<=9;i++){
if(!backup[i]) return false;
}
return true;
}
void dfs_c(int x,int num1,int num2){
if(x>6){
if(check(num1,num2)){
cnt++;
printf("%d %d %d\n",num1,num2,num1*C/A);
}
return;
}
for(int i=1;i<=9;i++){
if(!vis[i]){
vis[i]=1;
dfs_c(x+1,num1,num2*10+i);
vis[i]=0;
}
}
}
void dfs_a(int x,int num1){
if(x>3){
dfs_c(x,num1,0);
return;
}
for(int i=1;i<=9;i++){
if(!vis[i]){
vis[i]=1;
dfs_a(x+1,num1*10+i);
vis[i]=0;
}
}
}
int main(){
cin>>A>>B>>C;
dfs_a(1,0);
if(!cnt){
printf("No!!!");
}
return 0;
}