蓝桥杯JAVA B组 2017第二题 纸牌三角形

该文章是一个关于编程的问题,涉及到全排列算法的实现。给定9个数字(含A视为1)排成正三角形,要求每条边的数字和相等。提供的Java代码通过递归实现了全排列,并考虑到旋转和镜像的重复情况,最终结果需除以6。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.题目描述

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。

下图就是一种排法
      A
     9 6
    4   8
   3 7 5 2

这样的排法可能会有很多。

如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?

二.代码

public class test1{
    static int arr[] = {1,2,3,4,5,6,7,8,9};
    static int count = 0;
    public static void main(String[] args){
        f(0);
        System.out.println(count/6);//镜面两种情况,旋转三种情况,重复了3*2=6,所以最后结果要除以6
    }
    public static void f(int n){
        if(n==9){//结束递归
            //判断是否三边加起来和一样
            if(arr[0]+arr[1]+arr[2]+arr[3]==arr[3]+arr[4]+arr[5]+arr[6]&&arr[3]+arr[4]+arr[5]+arr[6]==arr[6]+arr[7]+arr[8]+arr[0]){
                count++;
            }
        }
        //全排列问题的解决模板:
        for(int i=n;i<9;i++){
            int t=arr[n];
            arr[n]=arr[i];
            arr[i]=t;
            f(n+1);
            t=arr[n];
            arr[n]=arr[i];
            arr[i]=t;
        }
    }
}

三.知识点

1.全排列问题分析:

把待全排列记录分为两个部分:
(1) 第一个记录
(2) 剩下的所有元素
所有记录的全排列就是所有可能出现在第一个位置的记录剩下所有元素的全排列
以[1,2,3]为例,
1,2,3的全排列可以看作是
   1,[2,3的全排列]
      [2,3]的全排列又可以看作是
         2,[3的全排列]—————对应123
         3,[2的全排列]—————对应132
   2,[1,3的全排列]
      [1,3]的全排列又可以看作是
         1,[3的全排列]—————对应213
         3,[1的全排列]—————对应231
   3,[1,2的全排列]
      [1,2]的全排列又可以看作是
         1,[2的全排列]—————对应312
         2,[1的全排列]—————对应321

递归的思想:给你部分记录,全排列就是所有可能出现在第一个位置的记录与剩下的元素的全排列,剩下的元素的全排列又是剩下的可能出现在第一个位置的元素剩下的元素的全排列,依次重复下去….

完整代码如下:
f方法接收三个参数,数组arr,起始位置start,终止为止end,意思就是完成arr数组从start到end之间记录的全排列。
分两个步骤:
(1)确定第一位的字符
数组arr从start到end的所有记录都可以出现在第一个位置,所以直接一个for循环,考虑了这所有的情况。在for循环中,交换i和start位置的数,保证当前i指向的记录出现在第一个位置,也就是start指向的位置
(2)剩下的记录继续做全排列
这个就是一个递归函数的调用,只需要修改起始位置,也就是start+1,因为start的位置已经放了记录,所以只需要继续做从start+1到end的全排列即可

因此为了保证每一次的交换不会对下一次的交换产生影响,要重新交换一下位置,也就是复原,不然对下一次的交换就有影响了

递归的终止条件就是当start==end,也就是只有一个记录需要做全排列,也就是到了最后一个记录,这就是全排列的一种情况,输出本次的记录,也就是数组arr即可。

2.全排列问题代码:

public class test1{
    static int arr[] = {1,2,3};
    public static void main(String[] args){
        f(arr,0,arr.length-1);//方法调用
    }
    public static void f(int []n,int start,int end){
        if(start==end){//结束条件
           for(int s:arr){//循环输出
               System.out.print(s);
           }
           System.out.println();//隔一行
        }
        for(int i=start;i<arr.length;i++){//递归函数交换
            int t=arr[start];
            arr[start]=arr[i];
            arr[i]=t;
            f(arr,start+1,arr.length-1);
            t=arr[start];//回溯
            arr[start]=arr[i];
            arr[i]=t;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值