网易2017---数列还原

题目描述

牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。

输入描述:

每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。

输出描述:

输出一行表示合法的排列数目。
示例1

输入

5 5
4 0 0 2 0

输出

2

题目链接

法一:dfs,惊奇的过了。全排列的变形,具体如下。代码如下(耗时25ms):
 1 public class Main {
 2 
 3     //vis标记已经排列的数1~n,不是标记已经排列的下标!!!
 4     static boolean[] vis = null;
 5     //记录每一个可能的排列数列
 6     static int[] res = null;
 7     //最后将符合标准的排列计数
 8     static int cnt = 0;
 9     
10     public static void main(String[] args) throws IOException {
11         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
12         String line = in.readLine();
13         String[] s = line.split(" ");
14         int n = Integer.parseInt(s[0]), k = Integer.parseInt(s[1]);
15         line = in.readLine();
16         s = line.split(" ");
17         vis = new boolean[n + 1];
18         res = new int[n + 1];
19         //初始化标记数组和结果数组,注意以下这里的下标,开始从1开始了
20         for(int i = 0; i < n; i++) {
21             if(!s[i].equals("0")) {
22                 res[i + 1] = Integer.parseInt(s[i]);
23                 vis[res[i + 1]] = true;
24             }
25         }
26         dfs(1, n, k);
27         System.out.println(cnt);
28     }
29     private static void dfs(int x, int n, int k) {
30         //递归终点
31         if(x == n + 1) {
32             int num = 0;
33             //校验标准是否通过,即i<j且a[i]<a[j],且对数是k
34             for(int i = 1; i < n; i++) {
35                 for(int j = i + 1; j < n + 1; j++) {
36                     if(res[i] < res[j]) {
37                         num++;
38                     }
39                 }
40             } 
41             //如果标准通过,计数cnt
42             if(num == k) {
43                 cnt++;
44             }
45             return;
46         }
47         //如果初始已经有值,则直接dfs下一个位置,类似于数独的初始化
48         if(res[x] != 0) {
49             dfs(x + 1, n, k);
50         }
51         //这里的i表示可排列的1~n的元数据,因为没有用数组存起来,所以这里直接从1开始
52         for(int i = 1; i <= n; i++) {
53             //校验当前数据是否已经在排列中,如果不在排列中,则放入排列即可
54             if(vis[i] == false) {
55                 vis[i] = true;
56                 res[x] = i;
57                 dfs(x + 1, n, k);
58                 res[x] = 0;
59                 vis[i] = false;
60             }
61         }
62     }
63 
64 }
View Code
原文地址:https://www.cnblogs.com/cing/p/8629393.html