蓝桥杯 java 牌型种数(暴力+递归+动态规划)

本文介绍了三种解决蓝桥杯算法问题——计算牌型种数的方法:1) 暴力枚举,通过for循环遍历所有可能的组合;2) 递归查询,利用递归思想逐步解决问题;3) 动态规划,采用二维数组记录状态并进行状态转移。同时提供了对应的Java代码示例。

牌型种数

1.基本原理

第一种,暴力枚举,也就是13种牌,每种牌被选择的情况为0,1,2,3,4。只要13张牌。
注意不是单一组合排序,因为会重复,比如1122,求C52(13),会出现不止一次。

第二种,递归查询,实际也就是step 有13 步,每步会有5中情况,n(表示牌),n+1,n+2,n+3,n+4,直到n=13的时候为递归的基本情况

第三种,动态规划,也就是状态迁移,考虑两个变量(牌的种类,牌收集的个数),使用二维数组,b[x][y] 表示x种牌,要收集y种的情况有多少,也就是我们要求b[13][13]是多少。

2.代码:

2.1for循环

比较容易理解,13种情况,总和是13就可以计数

package four_two;

public class Main02 {
    public static void main(String[] args) {
        find();
    }

    static void find() {
        int ans = 0;
        for (int one = 0; one < 5; one++)//第一种,可以取的种类有5种。
            for (int two = 0; two < 5; two++) //第二种
                for (int three = 0; three < 5; three++) //第三种
                    for (int four = 0; four < 5; four++) //第四种
                        for (int five = 0; five <5; five++)
                            for (int six = 0; six < 5; six++)
                                for (int serven = 0; serven < 5; serven++)
                                    for (int eight = 0; eight < 5; eight++)
                                        for (int nine = 0; nine < 5; nine++)
                                            for (int ten = 0; ten < 5; ten++)
                                                for (int eleven = 0; eleven < 5; eleven++)
                                                    for (int twoleve = 0; twoleve <5 ; twoleve++)
                                                        for (int threeteen = 0; threeteen < 5; threeteen++) {
                                                            int sum = one+two+three+four+five+six+serven+eight+nine+ten+eleven+twoleve+threeteen;
                                                            if(sum==13) {
                                                                ans++;
                                                               
                                                            }
                                                        }

        System.out.println(ans);


    }

2.2递归查询

	static int f(int n,int m) {
		if(n==0)
			return m==0?1:0;
		if(m==0)//这个属于剪枝把,填空题没有也没事
			return 1;
		if(m<0)//边界判断
			return 0;
		
		return f(n-1,m) + f(n-1,m-1) + f(n-1,m-2) +f(n-1,m-3)+f(n-1,m-4);
	}

2.3动态规划

动态规划确定几件事。
第一:用几维数组,这里用二维;
第二:下标表示什么含义,这里x表示牌的种类,y表示收集牌的个数
第三:怎么初始化?从已知条件下,应该是x=1,y=0,1,2,3,4 结果都是等于1.
但是如果从另外一个角度想,第二种牌,x=2,y=0,1,2,3,4 其实也是等于1,也就是,无论是第几种牌,抽0-4,其实都是1种情况,毕竟不考虑花色的话。

所以的的最开始思路是,初始化int[][] a = new int[14][5], 而每一项,都是1,举例来说a[13][2]=1.表示的就是第13种牌,抽两张出来的情况是1种。(虽然后面这个数组是多余的,但是有助于理解)

a数组并不能求解答案,所以还需要b数组,b[x][y],这时候表示的就是x种牌(不是第x种牌),收集y张牌的情况有多少种,比如b[2][3]=?,表示的是有两种牌,要收集3张的情况有多少种
(3种,分别是
a[2][0]x b[1][3]
:第二种牌选0种的时候,一种牌选3种的时候
a[2][1]x b[1][2]:第二种牌选1种的时候,一种牌选2种的时候
a[2][2]x b[1][1]:第二种牌选2种的时候,一种牌选1种的时候
a[2][3]x b[1][0]:第二种牌选3种的时候,一种牌选0种的时候
由于a[x][y] 都等于1,所以可以直接表示为 b[1][3] ,b[1][2], b[1][1],b[1][0] 这几种情况。

对每一种牌,只有4种选择
因此有下面的代码:

package four_two;

import java.util.Arrays;

public class Main03 {
    public static void main(String[] args) {
        check();
    }

    static void check(){
//填充,全部初始化为1
        int[][] a= new int[14][5];
        for (int[] aa : a) {
            Arrays.fill(aa,1);
            Arrays.fill(a,aa);
        }
        int[][] b= new int[14][14];
        b[1][0] =b[1][1]=b[1][2]=b[1][3]=b[1][4]= 1;
        for (int i = 1; i < 14; i++) {
            for (int j = 0; j < 14; j++) {
             if(j>i*4) b[i][j] = 0;//越界了,不存在a[2][9]这玩意。
             else
                 for (int k = 0; k <=4 ; k++) {//每一种,都只有4种选择,剩下的交给i-1 种选。
                     if(j-k>=0)
                     b[i][j] +=b[i-1][j-k];
                 }
            }
        }
        System.out.println(b[13][13]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值