纸牌三角形
标题:纸牌三角形
A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法(如有对齐问题,参看p1.png)。
A
9 6
4 8
3 7 5 2
这样的排法可能会有很多。
如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?
请你计算并提交该数字。
注意:需要提交的是一个整数,不要提交任何多余内容。
思路
这道题刚刚看到的时候,我第一个想到的就是既然要考虑到旋转和镜像去重问题,那我确定三角形的三个顶点即可确定一个等边三角形,这样只需要将三角形周长45加上三角形确定的三个顶点的和取模,等于零的解即为排法数量。(不知道有没有小伙伴有和我一样的想法)
错解
嗯,事实证明,这样行不通,我最初的代码如下:
public class TEST {
public static void main(String[] args) {
int[] a= {1,2,3,4,5,6,7,8,9};
int sum=0,summ=0;
double a1=0;
int total=0;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
for(int l=0;l<9;l++)
{
if(i!=j&&i!=l&&j!=l)
{
total++;
summ=a[i]+a[j]+a[l];
sum=45+summ;
a1=sum%3;
if(a1==0) {
total++;
System.out.println("a["+i+"]"+"、a["+j+"]"+"、a["+l+"]");
}
}
}
}
}
System.out.println(total);
}
}
运行后的结果:180
与答案144不符,错误。所以我发现我的想法有问题,180个里面有36个不能实现等边三角形。
正解
1.这道题是全排列问题
2. 全排列问题可以通过暴力排列、dfs搜索方法实现
3. 计算结束,注意去重问题 ,旋转有三种三角形,镜像有两种三角形,所以最后 计算结果要除以3,除以2,总共除以6.
暴力排序方法
import java.util.*;
public class TEST{
public static void main(String[] args) {
int sum=0;
for(int a=1; a<=9; a++)
for(int b=1; b<=9; b++) {
if(b==a) continue;
for(int c=1; c<=9; c++) {
if(c==a||c==b) continue;
for(int d=1; d<=9; d++) {
if(d==a||d==b||d==c) continue;
for(int e=1; e<=9; e++) {
if(e==a||e==b||e==c||e==d) continue;
for(int f=1; f<=9; f++) {
if(f==a||f==b||f==c||f==d||f==e) continue;
for(int g=1; g<=9; g++) {
if(g==a||g==b||g==c||g==d||g==e||g==f) continue;
for(int h=1; h<=9; h++) {
if(h==a||h==b||h==c||h==d||h==e||h==f||h==g)continue;
for(int i=1; i<=9; i++) {
if(i==a||i==b||i==c||i==d||i==e||i==f||i==g||i==h)continue;
if(a+b+d+f==a+c+e+i && a+b+d+f == f+g+h+i)sum++;
}
}
}
}
}
}
}
}
System.out.println(sum/6);
}
}
dfs搜索
import java.util.Scanner;
public class TEST {
static int sum = 0;
static int a[] = new int[9];//表示A-9的纸牌
static int vis[] = new int[10];//表示纸牌是否使用
public static void main(String[] args) {
dfs(0);
System.out.println(sum/3/2);
}
public static void dfs(int n) {//n表示当前要操作的位置
if(n==9){
if(a[0]+a[1]+a[2]+a[3]==a[3]+a[4]+a[5]+a[6] && a[3]+a[4]+a[5]+a[6]==a[6]+a[7]+a[8]+a[0]){
sum++;//如果是等边三角形,则sum++
}
return ;
}
for(int i=1;i<=9;i++){
if(vis[i]==0){//如果纸牌未被使用过
a[n]=i;//将第n个位置放置第i个纸牌
vis[i]=1;//表示第i纸牌已经被使用
dfs(n+1);//进入下一个位置
vis[i]=0;//将当前纸牌放回
}
}
}
}