算法(三)回溯算法概括

大多数的回溯算法都是需要填充的和给出的总数是相等的,比如前面提到的N皇后问题,一共给了N个皇后,一共也只需要填充N次;再比如前面提到的方格填数问题,一共10个空格,而给的数也是10个。下面来看两个问题,需要填充的和给出的总数是不相等的。

一、抽签问题

1.题目:

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行)

2.分析:这里一共需要填充5个,而给出的总数却不只5个,

3.代码如下:

 

<span style="color:#330099">package 回溯;

public class 抽签  

{  
	private static int count=0;
    /*遍历到第k个国家,还剩下n个空位置*/  
    public static void f(int[] a, int k, int n, String s)  
    {  
        if(k==a.length){/*遍历到第6个国家,没有空位*/  
        	count++;
            if(n==0)
            	System.out.println(s);  
            	
            return;  
        }  
          
        String s2 = s;  
        //每个国家开始,每个国家出i个人  
        for(int i=0; i<=a[k]; i++){  
            f(a, k+1, n-i, s2);   //填空位置  
            s2 += (char)(k+'A');  
        }  
    }  
      
    public static void main(String[] args)  
    {  
        int[] a = {4,2,2,1,1,3};  
        f(a,0,5,""); 
        System.out.print(count);
    }  
}  </span>

注:其实这题也可以用上一篇介绍的普通回溯法来求解,设一个a[5]的数组表示待填充的空格,然后a[i]的值可以为A、B、C、D、E,每次填充判断一下A、B、C、D、E的数量有没有超额,和“李白打酒问题”比较相似,只不过这样在判断条件的时候会麻烦一点。

二、牌型种数问题

 

1.


牌型种数

小明被劫持到X赌城,被迫与其他3人玩牌。
一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。
这时,小明脑子里突然冒出一个问题:
如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?

请填写该整数,不要填写任何多余的内容或说明文字。

 

2.分析:这里和上一题一样,也是需要填充的(13张)和给出总数不一样(一共52张),不过不同的是,上面一题组合的种数不确定,这里组合的种数是确定的(4个人,即4种)。

3.代码:

 

<span style="color:#330099">package 回溯;




public class 牌型种数 {
	public static int sum = 0; 
    public static int count = 0;


    public static void calculate(int kind)
    //kind表示牌的种数,sum表示总人数
    {
        if(sum>13||kind>13)
            return;
        if(kind == 13&& sum == 13)
        {
            count ++;
          
        }


        if(kind<13)
        {
            int i;
            for(i=0;i<5;i++)
            {
                sum += i;
                calculate(kind + 1);
                sum -= i;    //回溯的时候一定要记住还原标记哦!!!!!!
            }
        }


    }


    public static void main(String[] args){
        calculate(0);
        System.out.println(count);
    }
}</span>

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值