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

被折叠的 条评论
为什么被折叠?



