抽签 深度优先(排列组合) 详解

!!:该题与其他深度优先的题目不同的是,该题目的每个结点赋值可选域相互不影响。比如,一些深度优先的题目,结点共用一个集合,比如一些取数判断条件的深度优先题目。该题目中的每个结点的可选域为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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值