通过这几天的刷题,发现蓝桥惯出的一种题型----全排列+check()。
也就是在求出所有全排列的结果后,并检查每种结果是否满足题目的条件得出最终答案。
一、核心
递归式全排列或字典序式全排列
补:有重复元素求全排列,要求结果不重复时,要用字典序求解,递归求解会重复的(eg:前两个元素相同,第二个元素和第一个元素交换位置的排列结果和第一种结果相同)。
二、代码实现
1.递归式(未按字典序输出)
import java.util.Scanner;
public class Permutations {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] arr=new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i]=i+1;
}
permutation(arr,0);
}
private static void permutation(int[] arr, int start) {
if (start==arr.length) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
for (int i = start; i < arr.length; i++) {
swap(arr, start, i);
permutation(arr, start+1);
swap(arr, start, i);
}
}
private static void swap(int[] arr,int i,int j) {
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
2.字典序
import java.util.Scanner;
public class PermutationsWithDictionary {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] arr=new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i]=in.nextInt();
}
permutation(arr);
}
private static void permutation(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
while (true) {
int index1=-1;
int index2=-1;
for (int i = arr.length-2; i >=0; i--) {
if (arr[i]<arr[i+1]) {
index1=i;
break;
}
}
if (index1==-1) {
return;
}
for (int i = arr.length-1; i >=index1+1; i--) {
if (arr[i]>arr[index1]) {
index2=i;
break;
}
}
swap(arr, index1, index2);
reverse(arr,index1+1,arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
private static void reverse(int[] arr, int left,int right) {
for (int i = left,j=right; i < j; i++,j--) {
swap(arr, i, j);
}
}
private static void swap(int[] arr,int i,int j) {
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
三、历年真题
注:前面的标号对应于该题在竞码平台的题目id
7005 寒假作业
7006 剪邮票
7011 凑算式
7019 搭积木
1.寒假作业
package lanqiaobei_page1;
import java.util.Scanner;
public class T7005 {
static int ans = 0;
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
permutation(arr, 0);
System.out.println(ans);
}
private static void permutation(int[] arr, int start) {
if (start == arr.length) {
if (check(arr)) {
ans++;
}
}
for (int i = start; i < arr.length; i++) {
swap(arr, i, start);
permutation(arr, start + 1);
swap(arr, i, start);
}
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
private static boolean check(int[] ia) {
if (ia[0] + ia[1] == ia[2] && ia[3] - ia[4] == ia[5] && ia[6] * ia[7] == ia[8] && ia[10] * ia[11] == ia[9]) {
return true;
}
return false;
}
}
2.剪邮票
package lanqiaobei_page1;
//有一定难度,涉及到全排列和检查连通性。(以及一维数组如何转成二维数组)
//题型:有相同元素的数组求没有重复结果的全排列。
public class T7006 {
static int ans = 0;
public static void main(String[] args) {
// 注意第一个数组要是字典序最小的那个。
// 用字典序求出来的全部排列是不重复的,所以这道题要用这个方法求解,用递归求出的所有排列有重复的,结果当然也会重复。
int[] ia= {0,0,0,0,0,0,0,1,1,1,1,1};
permutation(ia);
System.out.println(ans);
}
private static void permutation(int[] arr) {
int[][] temp=new int[3][4];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
temp[i][j]=arr[i*4+j];
}
}
// 第一个排列,转换成二维数组后,检查是否只有一个连通图。
if (check(temp)) {
ans++;
}
while (true) {
int index1=-1;
int index2=-1;
for (int i = arr.length-2; i >=0; i--) {
if (arr[i]<arr[i+1]) {
index1=i;
break;
}
}
if (index1==-1) {
return;
}
for (int i = arr.length-1; i >=index1+1; i--) {
if (arr[i]>arr[index1]) {
index2=i;
break;
}
}
swap(arr, index1, index2);
reverse(arr,index1+1,arr.length-1);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
temp[i][j]=arr[i*4+j];
}
}
if (check(temp)) {
ans++;
}
}
}
private static boolean check(int[][] map) {
int cnt=0;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
if (map[i][j]==1) {
dfs(map,i,j);
cnt++;
}
}
}
if (cnt==1) {
return true;
}
return false;
}
private static void dfs(int[][] map, int i, int j) {
int row=map.length;
int col=map[0].length;
map[i][j]=0;
if (i-1>=0 && map[i-1][j]==1) dfs(map, i-1, j);
if (i+1<row && map[i+1][j]==1) dfs(map, i+1, j);
if (j-1>=0 && map[i][j-1]==1) dfs(map, i, j-1);
if (j+1<col && map[i][j+1]==1) dfs(map, i, j+1);
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
private static void reverse(int[] arr, int left,int right) {
for (int i = left,j=right; i < j; i++,j--) {
swap(arr, i, j);
}
}
}
3.凑算式
package lanqiaobei_page1;
//想错了,结果应该是通分后整除的结果是10,误想成了每个结果四舍五入后之和是10
import java.util.Scanner;
public class T7011 {
static int ans = 0;
public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
permutation(arr, 0);
System.out.println(ans);
}
private static void permutation(int[] arr, int start) {
if (start == arr.length) {
if (check(arr)) {
ans++;
}
}
for (int i = start; i < arr.length; i++) {
swap(arr, start, i);
permutation(arr, start + 1);
swap(arr, start, i);
}
}
private static boolean check(int[] arr) {
int fenzi=arr[3] * 100 + arr[4] * 10 + arr[5];
int fenmu=arr[6] * 100 + arr[7] * 10 + arr[8];
if ((arr[1]*fenmu+arr[2]*fenzi)%(arr[2]*fenmu)==0 && arr[0]+(arr[1]*fenmu+arr[2]*fenzi)/(arr[2]*fenmu)==10) {
return true;
}
return false;
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
4.搭积木
package lanqiaobei_page1;
public class T7019 {
static int ans=0;
public static void main(String[] args) {
int[] arr=new int[] {0,1,2,3,4,5,6,7,8,9};
permutation(arr,0);
System.out.println(ans);
}
private static void permutation(int[] arr, int start) {
if (start==arr.length) {
if (check(arr)) {
ans++;
}
}
for (int i = start; i < arr.length; i++) {
swap(arr,i,start);
permutation(arr, start+1);
swap(arr,i,start);
}
}
private static boolean check(int[] arr) {
if (arr[0]<arr[1] && arr[0]<arr[2] && arr[1]<arr[3] && arr[1]<arr[4] && arr[2]<arr[4]
&& arr[2]<arr[5] && arr[3]<arr[6] && arr[3]<arr[7] && arr[4]<arr[7] && arr[4]<arr[8]
&& arr[5]<arr[8] && arr[5]<arr[9] ) {
return true;
}
return false;
}
private static void swap(int[] arr, int i, int j) {
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}