" Algorithm Competition: 300 Quick Questions " will be published in 2024 and is an auxiliary exercise book for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
Codes are given in three languages: C/C++, Java, and Python. The topics are mainly mid- to low-level topics and are suitable for entry-level and advanced students.
Article directory
" Misplaced arrangement ", link: http://oj.ecustacm.cn/problem.php?id=1770
Question description
[Problem Description] For an arrangement a of length n, if a[i]=i does not exist, it is called a misaligned arrangement. Output the first k dislocations in lexicographic order.
[Input format] The input contains two positive integers n and k. The input ensures that n does not exceed 1000 and n*k does not exceed 100000.
[Output format] Output k lines, with n integers in each line representing a permutation.
【Input sample】
样例1:
2 1
样例2:
3 2
【Output sample】
样例1:
2 1
样例2:
2 3 1
3 1 2
answer
Before doing this question, let's review the classic application of DFS: output the full arrangement of n numbers in lexicographic order.
The following DFS code can print the arrangement from small to large. The premise is that the numbers in array a[20] are from small to large. If not, sort them first. Use b[] to record a new full arrangement. When entering dfs() for the first time, b[0] selects one of n numbers; when entering dfs() for the second time, b[1] selects one of the remaining n- Select one number from 1;...; until n numbers are selected, a full arrangement is obtained. Use vis[] to record whether a certain number has been selected. The selected number cannot be selected later.
Code output: "1 2 3; 1 3 2; 2 1 3; 2 3 1; 3 1 2; 3 2 1;"
C++ code 1
#include<bits/stdc++.h>
using namespace std;
int a[20]={
1,2,3,4,5,6,7,8,9,10,11,12,13};
bool vis[20]; //记录第i个数是否用过
int b[20]; //生成的一个全排列
void dfs(int s,int t){
if(s==t) {
//递归结束,产生一个全排列
for(int i=0; i<t; ++i) cout<<b[i]<<" "; //输出一个排列
cout<<"; ";
return;
}
for(int i=0;i<t;i++)
if(!vis[i]){
vis[i]=true;
b[s]=a[i];
dfs(s+1,t);
vis[i]=false;
}
}
int main(){
int n=3;
dfs(0,n); //前n个数的全排列
return 0;
}
[Key Points] Use DFS to output the complete arrangement in lexicographic order.
C++ code 2
Returning to this question, if you want to output a misaligned arrangement, you only need to slightly modify the above code and skip the arrangement of a[i]=i.
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, k;
int b[N];
bool vis[N];
int num=0; //统计已经输出的全排列数量
void dfs(int s){
if(s == n) {
for(int i=0;i<n;i++) printf("%d ",b[i]);
printf("\n");
num++; //输出了一个排列,num数量加1
return;
}
if(num == k) return; //只输出前k个
for(int i=1;i<=n;i++) {
if(i == s+1) continue; //处理错位:跳过a[i]=i的情况
if(!vis[i]){
vis[i] = true;
b[s] = i;
dfs(s+1);
vis[i] = false;
}
}
}
int main(){
cin >> n >> k;
dfs(0); //前n个数的全排列
return 0;
}
Java code 1
Output the fully arranged code
import java.util.*;
public class Main {
static int[] a = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
static boolean[] vis = new boolean[20];
static int[] b = new int[20];
public static void dfs(int s, int t) {
if (s == t) {
for (int i = 0; i < t; ++i) System.out.print(b[i] + " ");
System.out.print("; ");
return;
}
for (int i = 0; i < t; i++) {
if (!vis[i]) {
vis[i] = true;
b[s] = a[i];
dfs(s + 1, t);
vis[i] = false;
}
}
}
public static void main(String[] args) {
int n = 3;
dfs(0, n);
}
}
Java code 2
The code for this question
import java.util.*;
public class Main {
static int N = 1010;
static int n, k;
static int[] b = new int[N];
static boolean[] vis = new boolean[N];
static int num = 0; // 统计已经输出的全排列数量
public static void dfs(int s) {
if (s == n) {
for (int i = 0; i < n; i++) System.out.print(b[i] + " ");
System.out.println();
num++; // 输出了一个排列,数量加1
return;
}
if (num == k) return; // 只输出前k个
for (int i = 1; i <= n; i++) {
if (i == s+1) continue; // 处理错位:跳过a[i]=i不输出
if (!vis[i]) {
vis[i] = true;
b[s] = i;
dfs(s+1);
vis[i] = false;
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
k = sc.nextInt();
dfs(0); // 前n个数的全排列
}
}
Python code 1
Output the fully arranged code
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
vis = [False] * 20
b = [0] * 20
def dfs(s, t):
if s == t:
for i in range(t): print(b[i], end=" ")
print("; ", end="")
return
for i in range(t):
if not vis[i]:
vis[i] = True
b[s] = a[i]
dfs(s + 1, t)
vis[i] = False
n = 4
dfs(0, n)
Python code
The code for this question
N = 1010
n, k = map(int, input().split())
b = [0] * N
vis = [False] * N
num = 0 # 统计已经输出的全排列数量
def dfs(s):
global num
if s == n:
print(*b[:n])
num += 1 # 输出了一个排列,数量加1
return
if num == k: return # 只输出前k个
for i in range(1, n + 1):
if i == s + 1: continue # 处理错位:跳过a[i]=i不输出
if not vis[i]:
vis[i] = True
b[s] = i
dfs(s+1)
vis[i] = False
dfs(0) # 前n个数的全排列