2017-02 纸牌三角形

day3

题目描述

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
A,2,3,4,5,6,7,8,9共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等.
例如

     A
    9 6
   4   8
  3 7 5 2
这样的排法可能会有很多,如果考虑旋转,镜像后相同的算同一种,一共有多少种不同的排法呢?
请你计算并提交该数字

题目分析:

这是一道典型的全排列题型,我们给每个位置上的数字都编上号,将其存放在数组中,定义三个变量存储每条边的和,三边相等作为判断条件

本题有一个关键点:考虑旋转、镜像后相同的算同一种
因为三角形有三个角,也就是说每个数字都能在三个角上出现一次,所以旋转后相同算同一种的话,就需要将全排列总数 / 3;
镜像就是2分一模一样的数据,所以镜像后算同一种的话,就需要将全排列总数 / 2;
最终计算结果就是 全排列总数 / 3 / 2,即总数 / 6;

题解

public class lq_2017_02 {
	static int[] a= {1,2,3,4,5,6,7,8,9};
	static int ans;
	static void f(int k) {
		//终止条件:只剩最后一个元素需要排列  此时可判断是否符合条件
		if(k==9) {
			int x1=a[0]+a[1]+a[3]+a[5];
			int x2=a[0]+a[2]+a[4]+a[8];
			int x3=a[5]+a[7]+a[6]+a[8];
			if(x1==x2&&x2==x3)
				ans++;
		}
		//镜像旋转  全排列思想
		for(int i=k;i<9;i++) {
			//交换a[k]与a[i] 让每一位元素都有在前的机会
			int t=a[k];
			a[k]=a[i];
			a[i]=t;
			//将除第一个元素外的其他元素继续做排列
			f(k+1);
			//将先前交换的元素换回来,以便后序交换
			t=a[k];
			a[k]=a[i];
			a[i]=t;
		}
	}
public static void main(String[] args) {
	f(0);
	System.out.println(ans/6);
}
}

所以答案是144种

知识点补充:

JAVA中的全排列:

全排列的基本思想是:
把待全排列记录分为两个部分:
(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

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

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

至于紧接着的一个swap方法是做什么的呢?因为数组传递的是地址,所以所有的修改对所有人都是共享的,因此为了保证每一次的交换不会对下一次的交换产生影响,要重新交换一下位置,也就是复原,不然对下一次的交换就有影响了

递归的终止条件就是当start==end,也就是只有一个记录需要做全排列,也就是到了最后一个记录,这就是全排列的一种情况,输入本次的记录,也就是数组arr即可。
原文链接:https://blog.csdn.net/qq_16403141/article/details/80548282

public class Main {
    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4 };
        fullSort(arr, 0, arr.length - 1);
    }

    public static void fullSort(int[] arr, int start, int end) {
        // 递归终止条件
        if (start == end) {
            for (int i : arr) {
                System.out.print(i);
            }
            System.out.println();
            return;
        }
        for (int i = start; i <= end; i++) {
            swap(arr, i, start);
            fullSort(arr, start + 1, end);
            swap(arr, i, start);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

}

  • 27
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值