!!:该题与其他深度优先的题目不同的是,该题目的每个结点赋值可选域相互不影响。比如,一些深度优先的题目,结点共用一个集合,比如一些取数判断条件的深度优先题目。该题目中的每个结点的可选域为a[]数组中的元素。可以理解为下标表示国家,即结点,索引元素表示最多可选人数的上限。
抽签
X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
….
那么最终派往W星的观察团会有多少种国别的不同组合呢?
下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
….
(以下省略,总共101行)
#include <stdio.h>
#include<iostream>
#define N 6
#define M 5
#define BUF 1024
void f(int a[], int k, int m, char b[])
{
int i,j;
if(k==N)//判断是不是到最后一个国家,即F,由此可判断是一个递归且,k每次递增
{
b[M] = 0;//把尾部设为\0
if(m==0) printf("%s\n",b);//如果传进来的m==0,即打出字符串,可以猜出m是表示不用再选人了
return;//到了第六个国家,要么打印后return,要么不打印return
}
for(i=0; i<=a[k]; i++)
{
for(j=0; j<i; j++)
b[M-m+j] = k+'A';
f(a,k+1,m-i,b); //填空位置
}
}
int main()
{
int a[N] = {4,2,2,1,1,3};
char b[BUF];
f(a,0,M,b);
system("pause");
return 0;
}
思路是这样的:先来到A国,A派0人,来到B国,B派0人......C......D.....E,这样下去一直到F国,F国派人,再进行递归时k == 6,所以到了F能派的都派完,即派到3人还是没有达到五人,所以退到E,E i++派出一人,继续来到F,同样,F只能到3人,退出来到E,而E只能派一人,退出来到D,D派1人,再进入E.....就是这样一层层递归到最后的。根据思路,我自己再写了一遍。写的时候发现,蓝桥杯提供的代码可以优化许多。也可以不用写得那么难看懂。
#include<iostream>
#define N 6
#define M 2
#define BUF 1024
using namespace std;
void f(int *a,char *b,int con,int num)
{
int i,j;
if(num == M)//这个先判断
{
b[num] = 0;
cout << b << '\n';
return;
}
else if(con == 6)
{
return ;
}
for(i = 0;i <= a[con];i++)
{
for(j = 0;j < i;j++)
{
b[num + j] = 'A' + con;
}
f(a,b,con+1,num+i);
}
}
int main()
{
int a[N] = {4,2,2,1,1,3};
char b[BUF];
f(a,b,0,0);
system("pause");
return 0;
}