"Algorithm Competition·Quick 300 Questions" One question per day: "Misplaced Arrangement"

" 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.


" 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】

样例12 1

样例23 2

【Output sample】

样例12 1

样例22 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个数的全排列

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/132447854