全排列应用--搭积木/凑算式/随机组合/方格填数/寒假作业

1.凑算式
     B      DEF
A + --- + ------- = 10
     C      GHI 
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

思路:对1-9进行全排列
限制:C,D,G不能为0

package 凑算式;

import java.util.Arrays;

public class Main {
	static int a[]=new int[9];
	static boolean used[]=new boolean[10];
	static int ants=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Arrays.fill(used,false);
		dfs(0);
		System.out.println(ants);
	}
	public static void dfs(int x){
		if(x==9){
			if(a[2]==0||a[6]==0||a[3]==0) return ;
			if(Math.abs(a[0]+1.0*a[1]/a[2]+1.0*(a[3]*100+a[4]*10+a[5])/(a[6]*100+a[7]*10+a[8])-10)<1e-6){
				ants++;
			}
			return ;
		}
		for(int i=1;i<10;i++){
			if(!used[i]){
				a[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;
			}
		}
	}
	
}

2.随机组合

小明被绑架到X星球的巫师W那里。其时,W正在玩弄两组数据 (2 3 5 8) 和 (1 4 6 7)。他命令小明从一组数据中分别取数与另一组中的数配对,共配成4对(组中的每个数必被用到)。
小明的配法是:{(8,7),(5,6),(3,4),(2,1)}。师凝视片刻,突然说这个配法太棒了!
因为:每个配对中的数字组成两位数,求平方和,无论正倒,居然相等:
87^2 + 56^2 + 34^2 + 21^2  =  12302
78^2 + 65^2 + 43^2 + 12^2  =  12302
小明想了想说:“这有什么奇怪呢,我们地球人都知道,随便配配也可以啊!”
{(8,6),(5,4),(3,1),(2,7)}
86^2 + 54^2 + 31^2 + 27^2 = 12002
68^2 + 45^2 + 13^2 + 72^2 = 12002
巫师顿时凌乱了。。。。。请你计算一下,包括上边给出的两种配法,巫师的两组数据一共有多少种配对方案具有该特征。

全排列问题,有固定模板

package 随意组合;

public class Main {
	static int num1[]={2,3,5,8};
	static int num2[]={1,4,6,7};
	static int num[]=new int[4];
	static boolean used[]=new boolean[4];
	static int ants=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=0;i<4;i++) used[i]=false;
		dfs(0);
		System.out.println(ants);
	}
	public static boolean ok(){
		int p1=0,p2=0;
		for(int i=0;i<4;i++){
			p1+=(num1[i]*10+num2[num[i]])*(num1[i]*10+num2[num[i]]);
			p2+=(num2[num[i]]*10+num1[i])*(num2[num[i]]*10+num1[i]);
		}
		return p1==p2;
	}
	public static void dfs(int x){
		if(x==4){
			if(ok()) ants++;
			return;
		}
		for(int i=0;i<4;i++){
			if(used[i]==false){
				num[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;
			}
		}
	}

}

3.搭积木
小明最近喜欢搭数字积木,一共有10块积木,每个积木上有一个数字,0~9。
搭积木规则:每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
最后搭成4层的金字塔形,必须用完所有的积木。下面是两种合格的搭法:
   0
  1 2
 3 4 5
6 7 8 9


   0
  3 1
 7 5 2
9 8 6 4    
请你计算这样的搭法一共有多少种?
分析:

将四层金字塔看做一个4*4二维矩阵,对0-9进行全排列,且b[i][j]<b[i+1][j] ,b[i][j]<b[i+1][j+1]

package 搭积木;

import java.util.Arrays;

public class Main {
	static int a[]=new int[10];
	static boolean used[]=new boolean[10];
	static int ants=0;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Arrays.fill(used, false);
		dfs(0);
		System.out.println(ants);
	}
	public static boolean check(){
		int b[][]=new int[4][4];
		int k=0;
		for(int i=0;i<4;i++){
			for(int j=0;j<=i;j++){
				b[i][j]=a[k];
				k++;
			}
		}
		for(int i=0;i<3;i++){
			for(int j=0;j<=i;j++){
				if(b[i][j]>=b[i+1][j]||b[i][j]>=b[i+1][j+1]) return false;
			}
		}
		return true;
	}
	public static void dfs(int x){
		if(x==10){
			if(check()) ants++;
			return;
		}
		for(int i=0;i<10;i++){
			if(used[i]==false){
				a[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;				
			}
		}
	}

}

4.方格填数

如下的10个格子
   +--+--+--+
    |     |    |    |
+--+--+--+--+
|     |     |    |    |
+--+--+--+--+
|     |     |    |
+--+--+--+
入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?

解题思路:

方法一:

1.如何枚举?
给格子编号
   +--+--+--+
   | 0| 1| 2|
+--+--+--+--+
| 3| 4| 5| 6|
+--+--+--+--+
| 7| 8| 9|
+--+--+--+
格子的位置是不变的,枚举的是数字在哪个格子里
2.如何处理相邻?Hardcode:
Adj[i][j]=0//第i个盒子与第j个盒子没有相邻
int adj[10][10] = {     {0, 1, 0, 1, 1, 1, 0, 0, 0, 0},
                      {1, 0, 1, 0, 1, 1, 1, 0, 0, 0},
                        {0, 1, 0, 0, 0, 1, 1, 0, 0, 0},
                        {1, 0, 0, 0, 1, 0, 0, 1, 1, 0},
                        {1, 1, 0, 1, 0, 1, 0, 1, 1, 1},
                        {1, 1, 1, 0, 1, 0, 1, 0, 1, 1},
                        {0, 1, 1, 0, 0, 1, 0, 0, 0, 1},
                        {0, 0, 0, 1, 1, 0, 0, 0, 1, 0},
                        {0, 0, 0, 1, 1, 1, 0, 1, 0, 1},
                        {0, 0, 0, 0, 1, 1, 1, 0, 1, 0}};

3.对0-9个数字放置的格子进行全排列,表示:顺序的数字0-9对应的盒子。例排列0,1,2,……9:表示:0在0号格子,……9在9号格子
例:1,3,4,6,9,5,2,0,7,8 表示:0在1号格子,1在3号格子……
所以连续数字不相邻 判断条件为相邻的数字放置的格子不相邻
package 方格填数;

import java.util.Arrays;

public class Main {
	static int adj[][] = {	{0, 1, 0, 1, 1, 1, 0, 0, 0, 0},
   	       			{1, 0, 1, 0, 1, 1, 1, 0, 0, 0},
   	       			{0, 1, 0, 0, 0, 1, 1, 0, 0, 0},
   	       			{1, 0, 0, 0, 1, 0, 0, 1, 1, 0},
   	       			{1, 1, 0, 1, 0, 1, 0, 1, 1, 1},
   	       			{1, 1, 1, 0, 1, 0, 1, 0, 1, 1},
   	       			{0, 1, 1, 0, 0, 1, 0, 0, 0, 1},
   	       			{0, 0, 0, 1, 1, 0, 0, 0, 1, 0},
   	       			{0, 0, 0, 1, 1, 1, 0, 1, 0, 1},
   	       			{0, 0, 0, 0, 1, 1, 1, 0, 1, 0}};
	static int ants=0;
	static int a[]=new int[10];//数字放置的格子的全排列
	static boolean used[]=new boolean[10];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Arrays.fill(used, false);
		dfs(0);
		System.out.println(ants);
	}
	public static boolean check(){
		for(int i=0;i<9;i++){
			if(adj[a[i]][a[i+1]]==1) return false;
		}
		return true;
	}
	public static void dfs(int x){
		if(x==10){
			if(check()) ants++;
			return ;
		}
		for(int i=0;i<10;i++){
			if(!used[i]){
				a[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;
			}
		}
	}
}

方法二:与一相近,只是使用逻辑判断相邻,计算格子的位置坐标来判断,可以将格子的标号改为1-10,有利于/%判断

代码如下:

package 方格填数;

import java.util.Arrays;

public class Main {
	static int ants=0;
	static int a[]=new int[11];//数字放置的格子的全排列
	static boolean used[]=new boolean[11];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Arrays.fill(used, false);
		dfs(1);
		System.out.println(ants);
	}
	public static boolean adj(int x,int y){
		//计算x,y盒子的坐标
		int rx,cx,ry,cy;
		rx=x/4;cx=x%4;
		ry=y/4;cy=y%4;
		return Math.abs(rx-ry)<=1&&Math.abs(cx-cy)<=1;
	}
	public static boolean check(){
		for(int i=1;i<10;i++){
			if(adj(a[i],a[i+1])) return false;
		}
		return true;
	}
	public static void dfs(int x){
		if(x==11){
			if(check()) ants++;
			return ;
		}
		for(int i=1;i<=10;i++){
			if(!used[i]){
				a[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;
			}
		}
	}
}

5.寒假作业现在小学的数学题目也不是那么好玩的。看看这个寒假作业:   □ + □ = □   □ - □ = □   □ × □ = □   □ ÷ □ = □每个方块代表1~13中的某一个数字,但不能重复。比如: 6  + 7 = 13 9  - 8 = 1 3  * 4 = 12 10 / 2 = 5以及:  7  + 6 = 13 9  - 8 = 1 3  * 4 = 12 10 / 2 = 5就算两种解法。(加法,乘法交换律后算不同的方案) 你一共找到了多少种方案?注意÷需要能除尽解题思路:确定枚举的变量   a[0] + a[1] = □   a[2] – a[3] = □   a[4] × a[5] = □   a[6] ÷ a[7] = □?除尽

对a[0]-a[7]进行枚举所以x:[0,7]

代码如下:

package 寒假作业;

public class Main {
	static int a[]=new int[8];//枚举8个数
	static boolean used[]=new boolean[14];//14个数用没用过
	static int ants=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		dfs(0);//x枚举的个数
		System.out.println(ants);
	}
	public static void dfs(int x){
		int y=0;
		if(x==8){
			if(a[6]%a[7]!=0) return;
			y=a[6]/a[7];
			if(y>=1&&y<=13&&!used[y])ants++;
			return;
		}
		if(x==2) y=a[0]+a[1];
		if(x==4) y=a[2]-a[3];
		if(x==6) y=a[4]*a[5];
		if(y!=0&&(y<1||y>13||used[y])) return ;
		used[y]=true;
		for(int i=1;i<14;i++){
			if(!used[i]){
				a[x]=i;
				used[i]=true;
				dfs(x+1);
				used[i]=false;
			}
		}
		used[y]=false;
	}

}












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值