解题思路

这是一个排列组合问题,需要计算满足特定顺序对数量的排列个数。由于看不清的位置不超过10个,可以使用DFS暴力枚举所有可能的排列。

关键点:

  1. 识别未知位置(值为0的位置)
  2. 找出所有未使用的数字
  3. 计算顺序对的数量
  4. 使用DFS枚举所有可能的排列

算法步骤:

  1. 收集所有未使用的数字和未知位置
  2. DFS尝试在未知位置填入未使用的数字
  3. 计算每个排列的顺序对数量
  4. 统计满足条件的排列数量

代码

#include <bits/stdc++.h>
using namespace std;

class Solution {
private:
    vector<int> arr;
    vector<int> unused;
    vector<int> positions;
    int n, k, count = 0;
    
    int countInversions() {
        int inversions = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (arr[i] < arr[j]) {
                    inversions++;
                }
            }
        }
        return inversions;
    }
    
    void dfs(int pos) {
        if (pos == positions.size()) {
            if (countInversions() == k) {
                count++;
            }
            return;
        }
        
        for (int i = 0; i < unused.size(); i++) {
            arr[positions[pos]] = unused[i];
            swap(unused[i], unused.back());
            unused.pop_back();
            
            dfs(pos + 1);
            
            unused.push_back(arr[positions[pos]]);
            swap(unused[i], unused[unused.size() - 1]);
        }
    }
    
public:
    int solve(int N, int K, vector<int>& A) {
        n = N;
        k = K;
        arr = A;
        
        // 收集未使用的数字和未知位置
        vector<bool> used(n + 1, false);
        for (int i = 0; i < n; i++) {
            if (arr[i] != 0) {
                used[arr[i]] = true;
            } else {
                positions.push_back(i);
            }
        }
        
        for (int i = 1; i <= n; i++) {
            if (!used[i]) {
                unused.push_back(i);
            }
        }
        
        dfs(0);
        return count;
    }
};

int main() {
    int n, k;
    cin >> n >> k;
    
    vector<int> arr(n);
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    
    Solution solution;
    cout << solution.solve(n, k, arr) << endl;
    
    return 0;
}
import java.util.*;

public class Main {
    static class Solution {
        private int[] arr;
        private List<Integer> unused;
        private List<Integer> positions;
        private int n, k, count;
        
        private int countInversions() {
            int inversions = 0;
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    if (arr[i] < arr[j]) {
                        inversions++;
                    }
                }
            }
            return inversions;
        }
        
        private void dfs(int pos) {
            if (pos == positions.size()) {
                if (countInversions() == k) {
                    count++;
                }
                return;
            }
            
            for (int i = 0; i < unused.size(); i++) {
                arr[positions.get(pos)] = unused.get(i);
                Collections.swap(unused, i, unused.size() - 1);
                int last = unused.remove(unused.size() - 1);
                
                dfs(pos + 1);
                
                unused.add(last);
                Collections.swap(unused, i, unused.size() - 1);
            }
        }
        
        public int solve(int N, int K, int[] A) {
            n = N;
            k = K;
            arr = A.clone();
            count = 0;
            unused = new ArrayList<>();
            positions = new ArrayList<>();
            
            boolean[] used = new boolean[n + 1];
            for (int i = 0; i < n; i++) {
                if (arr[i] != 0) {
                    used[arr[i]] = true;
                } else {
                    positions.add(i);
                }
            }
            
            for (int i = 1; i <= n; i++) {
                if (!used[i]) {
                    unused.add(i);
                }
            }
            
            dfs(0);
            return count;
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        
        Solution solution = new Solution();
        System.out.println(solution.solve(n, k, arr));
        
        sc.close();
    }
}
class Solution:
    def __init__(self):
        self.arr = []
        self.unused = []
        self.positions = []
        self.n = 0
        self.k = 0
        self.count = 0
    
    def count_inversions(self):
        inversions = 0
        for i in range(self.n):
            for j in range(i + 1, self.n):
                if self.arr[i] < self.arr[j]:
                    inversions += 1
        return inversions
    
    def dfs(self, pos):
        if pos == len(self.positions):
            if self.count_inversions() == self.k:
                self.count += 1
            return
        
        for i in range(len(self.unused)):
            self.arr[self.positions[pos]] = self.unused[i]
            last = self.unused.pop(i)
            
            self.dfs(pos + 1)
            
            self.unused.insert(i, last)
    
    def solve(self, n: int, k: int, arr: list) -> int:
        self.n = n
        self.k = k
        self.arr = arr.copy()
        self.count = 0
        
        # 收集未使用的数字和未知位置
        used = [False] * (n + 1)
        self.positions = []
        
        for i in range(n):
            if arr[i] != 0:
                used[arr[i]] = True
            else:
                self.positions.append(i)
        
        self.unused = [i for i in range(1, n + 1) if not used[i]]
        
        self.dfs(0)
        return self.count

# 读取输入
n, k = map(int, input().split())
arr = list(map(int, input().split()))

solution = Solution()
print(solution.solve(n, k, arr))

算法及复杂度

  • 算法:DFS + 回溯
  • 时间复杂度:,其中 是未知位置的数量(≤10), 是序列长度
  • 空间复杂度:,需要存储序列和未使用的数字