全排列算法:蓝桥杯2017之纸牌三角形

纸牌三角形

    A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
    下图就是一种排法(如有对齐问题,参看p1.png)。

          A
         9 6
        4   8
       3 7 5 2

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

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

    请你计算并提交该数字。

    注意:需要提交的是一个整数,不要提交任何多余内容。

方法一:

这道题第一次看到,便想到是一个全排列的题,关键点在于如何保证全部的情况都考虑到,并且每种排列情况互不影响程序的进行。
那我的思路是直接抽象为一个9长度的一位数组,进行全排列。当然从1 2 3 4 5 6 7 8 9

这里用一个少的例子,先自己找找全排列的规律
A B C D
A B D C
A C B D
A C D B
A D C B
A D B C
B…
ok ,其实很自然地可以看到是从A开始判断过后,直接进行下一位B的判断一直到D…
然后在找到D过后 直接输出ABCD,然后再反着来从D开始全排列,
D排列完了就从ABCD这个原始数据的C开始进行向D的全排列 ,得到ABDC
然后就又从ABCD的原始数据的B开始向后全排列…一直进行下去。

到这里不难想到就是利用递归。但是关键点在于递归的参数值和递归结束的标志。

看代码,不断学习吧。

import java.util.Scanner;

public class Main{
	
	private static int count = 0;  //用这个来存储满足的情况
	
	public static void main(String[] args) {
		
		int[] a= {1,2,3,4,5,6,7,8,9};
		Sq(a, 0);
		System.out.println(count/6);//**为什么要除以6,因为我们是全排列,而题目要求 三角形旋转(3倍),镜像(2倍)算一种**
		//最后要除以6!!!!!!!
		
	}
	
	public static void Sq(int[] data, int k) {  //k代表当前的可以与后面的数字交换的位置
		
		if(k==data.length) {   //该递归函数结束条件为 每次k的位置变为data的最长时,退出,当然在此之前其实已经完成一个排列
			panduan(data);
			return;
		}
		
		//我们想要的是k位置的数字可以和之后的数字交换位置,进行排列,并且必要的还能恢复到原来的原始状态
		for(int i = k;i<data.length;i++) {  //i用来代表进行交换位置的下标,所以从k开始
		
			{                           //这一块交换也就是k标记下标 和 k后面的数字的一次交换
				int temp = data[k];
				data[k] = data[i];
				data[i] = temp;
			}
			
			Sq(data, k+1);             //k位置的一次交换过后 ,立马进行递归k+1位置的全排列,保证全排列的进行
			
			{                         //k位置的交换 以及 交换过后的k+1位置的全排列结束过后,再将k交换回来,保证原始数据没有发生变换!
			
				int temp = data[k];
				data[k] = data[i];
				data[i] = temp;
			}
			//因为两个交换,使得一次循环过后原始数据不变,这个时候进行下一次循环i++,k标记的位置就可以和i代表的k+2的位置的元素,进行交换,全排列,再还原了
		}
		
	}
	
	
	
	
	public static void panduan(int[] a) {
		if((a[0]+a[1]+a[2]+a[3])==(a[3]+a[4]+a[5]+a[6])&&((a[6]+a[7]+a[8]+a[0])==(a[3]+a[4]+a[5]+a[6]))) {
			count++;
		}
	}
	
	
}

生活和学习其实免不了“投机取巧”。学习再厉害,招数 学的再华丽,说不定都会被最普通的方法达到一样的效果。这样的事数不胜数,值得我们反思,有时候去解决一个问题,是否真的需要大费周章,常规思路的解法未尝不是一个好办法。

所以,接下来值得学习的暴力解决法。

方法二:暴力

public class Main {
	public static void main(String[] args) {
		int a, b, c, d, e, f, g, h, i;
		int sum = 0;
		for (a = 1; a < 10; a++) {
			for (b = 1; b < 10; b++) {
				for (c = 1; c < 10; c++) {
					for (d = 1; d < 10; d++) {
						for (e = 1; e < 10; e++) {
							for (f = 1; f < 10; f++) {
								for (g = 1; g < 10; g++) {
									for (h = 1; h < 10; h++) {
										for (i = 1; i < 10; i++) {
											if (a + b + d + f == a + c + e + i
													&& a + b + d + f == f + g
															+ h + i && a != b
													&& a != c && a != d
													&& a != e && a != f
													&& a != g && a != h
													&& a != i && b != c
													&& b != d && b != e
													&& b != f && b != g
													&& b != h && b != i
													&& c != d && c != e
													&& c != f && c != g
													&& c != h && c != i
													&& d != e && d != f
													&& d != g && d != h
													&& d != i && e != f
													&& e != g && e != h
													&& e != i && f != g
													&& f != h && f != i
													&& g != h && g != i
													&& h != i) {
												sum++;
											}
										}
									}
								}
							}
						}
					}
				}
			}
 
		}
		System.out.println(sum/3/2); //同样除以6
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42036647/article/details/88351443
今日推荐