《算法竞赛·快冲300题》每日一题:“错位排列”

news/2024/7/20 20:59:02 标签: 深度优先

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码1
  • C++代码2
  • Java代码1
  • Java代码2
  • Python代码1
  • Python代码

错位排列” ,链接: http://oj.ecustacm.cn/problem.php?id=1770

题目描述

【题目描述】 对于一个长度为n的排列a而言,如果不存在a[i]=i,则称之为一个错位排列。按照字典序输出前k个错位排列。
【输入格式】 输入包含两个正整数n和k。输入保证n不超过1000,n*k不超过100000。
【输出格式】 输出k行,每行n个整数表示一个排列。
【输入样例】

样例12 1

样例23 2

【输出样例】

样例12 1

样例22 3 1
3 1 2


题解

   在做本题之前,先回顾DFS的经典应用:按字典序输出n个数的全排列。
   下面的DFS代码能从小到大打印排列。前提是数组a[20]中的数字是从小到大的,如果不是,先排序。用b[]记录一个新的全排列,第一次进入bfs()时,b[0]在n个数中选一个;第二次进入bfs()时,b[1]在剩下的n-1个数中选一个;…;直到选了n个数为止,就得到了一个全排列。用vis[]记录某个数是否已经被选过,选用过的数不能在后面继续选。
   代码输出:“1 2 3 ; 1 3 2 ; 2 1 3 ; 2 3 1 ; 3 1 2 ; 3 2 1 ;”

C++代码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;
}

【重点】 用DFS按字典序输出全排列。

C++代码2

   回到本题,要求输出错位排列,只要对上面代码略作修改,跳过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代码1

输出全排列的代码

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代码2

本题的代码

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代码1

输出全排列的代码

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代码

本题的代码

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

http://www.niftyadmin.cn/n/4961762.html

相关文章

会计资料基础

会计资料 1.会计要素及确认与计量 1.1 会计基础 1.2 六项会计要素小结 1.3 利润的确认条件 1.3.1 利润的定义和确认条件 1.4 会计要素及确认条件 2.六项会计要素 2.1 资产的特征及其确认条件 这部分资产可以给企业带来经济收益&#xff0c;但是如果不能带来经济利益&#xff…

【LeetCode-中等题】3. 无重复字符的最长子串

题目 题解一&#xff1a;单指针&#xff0c;滑动窗口 思路&#xff1a; 设置一个左指针&#xff0c;来判断下一个元素是否在set集合中&#xff0c;如果不在&#xff0c;就加入集合&#xff0c;right继续&#xff0c;如果在&#xff0c;就剔除重复的元素&#xff0c;计算串的长度…

【C语言】喝汽水问题

大家好&#xff01;今天我们来学习C语言中的喝汽水问题&#xff01; 目录 1. 题目内容&#xff1a; 2. 思路分析 2.1 方法一 2.2 方法二 2.3 方法三 3. 代码实现 3.1 方法一 3.2 方法二 3.3 方法三 1. 题目内容 喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以…

ORB-SLAM系列算法演进

ORB-SLAM算法是特征点法的代表&#xff0c;当前最新发展的ORB-SLAM3已经将相机模型抽象化&#xff0c;适用范围非常广&#xff0c;虽然ORB-SLAM在算法上的创新并不是很丰富&#xff0c;但是它在工程上的创新确实让人耳目一新&#xff0c;也能更好的为AR、机器人的算法实现落地。…

【C++】UDP通信,实现文件的传输

目录 1 TCP与UDP比较 2 UDP 3 通信流程 4 实践 5 运行结果 1 TCP与UDP比较 2 UDP简介 UDP通信是无连接的,因此不需要

Vue使用Animate.css

说一下Animate.css这个动画库&#xff0c;很多的动画在这个库里面都定义好了&#xff0c;我们用的时候可以直接使用里面的类名就可以了&#xff0c;就是直接目标元素绑定对应的类名就可以实现动画效果&#xff0c;非常方便&#xff0c;库其实也相对简单&#xff0c;使用起来也简…

WPS office 最新未公开 0Day漏洞警示

一、事件描述 近日&#xff0c;网传监测发现WPS Office for Windows版本 存在0day漏洞&#xff0c;攻击者可以利用该0day漏洞在受害者主机上执行任意恶意文件&#xff0c;高危级别&#xff0c;官方尚未对此发布修复漏洞&#xff0c;目前建议只能临时弃用wps或者不要点开未知文件…

docker-compose部署服务

1. 安装docker-compose 1.1 手动下载地址 https://github.com/docker/compose/releases shell命令下载 $ sudo curl -L https://github.com/docker/compose/releases/download/2.17.12/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose1.2 添加执行权限 …