• 蓝桥杯 排列问题


    问题描述
      求一个0~N-1的排列(即每个数只能出现一次),给出限制条件(一张N*N的表,第i行第j列的1或0,表示为j-1这个数不能出现在i-1这个数后面,并保证第i行第i列为0),将这个排列看成一个自然数,求从小到大排序第K个排列。
    数据规模和约定
      N<=10,K<=500000
    输入格式
      第一行为N和K,接下来的N行,每行N个数,0表示不能,1表示能
    输出格式
      所求的排列
    样例输入
    3 2
    0 1 1
    1 0 0
    0 1 0

    样例输出

    1 0 2
    解释: 对于N=3的没有任何限制的情况 第一:0 1 2 第二:0 2 1 第三:1 0 2 第四:1 2 0 第五:2 0 1 第六:2 1 0 根据题目所给的限制条件由于2不能出现在1后面,0不能出现在2后面 第一:0 2 1 第二:1 0 2 第三:2 1 0
    参考自https://blog.csdn.net/weixin_44778155/article/details/104672498
    这道题目题意比较难理解,简单解释一下。
    首先我们生成一个0~n-1的全排列,比如n=3的时候,全排列按顺序为:
    第一:0 1 2
    第二:0 2 1
    第三:1 0 2
    第四:1 2 0
    第五:2 0 1
    第六:2 1 0
    然后我们给出了限制,这个限制是通过一个n*n的矩阵给出的,我们开一个二维数组vis[][]记录这个矩阵。
    在这个矩阵里,从左上往右下i=j这条对角线上的0没有用,我们不用看。
    我们只看其他位置有没有0,在样例里也就是vis[1][2]=0,vis[2][0]=0
    就是说2不能紧贴着跟在1的后面,中间隔了几个数然后2在1后面是可以的。所以上面六个全排列中的第一,第四不符合要求,删去。
    然后0不能紧贴着跟在2后面。上面的第五删去。
    所以剩下的全排列是:
    第一:0 2 1
    第二:1 0 2
    第三:2 1 0
    然后样例k=2,所以输出第二个全排列1 0 2
    然后这段代码就好理解了。
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n, k, cnt;
     4 int a[20];
     5 int vis[20][20];
     6 bool check() { //check函数用于判断当前这个全排列是否符合题意 
     7     for (int i = 1; i < n; i++) { //遍历这个全排列,看看是否存在某个数不能紧贴在某个数后面的情况 
     8         if (vis[a[i - 1]][a[i]] == 0) {
     9             return false;
    10         }
    11     }
    12     return true;
    13 }
    14 int main() { 
    15     cin >> n >> k;
    16     for (int i = 0; i < n; i++) {
    17         a[i] = i; //生成0~n-1的序列 
    18     }
    19     for (int i = 0; i < n; i++) { //输入限制 
    20         for (int j = 0; j < n; j++) {
    21             cin >> vis[i][j];
    22         }
    23     } 
    24     do {
    25         if (check()) { //判断这个序列是否符合要求 
    26             if (++cnt == k) { //若符合要求,++cnt。求到第k个符合条件的全排列的话,break 
    27                 break;
    28             }
    29         } 
    30     } while (next_permutation(a, a + n));
    31     for (int i = 0; i < n; i++) { //输出这个全排列 
    32         cout << a[i] << " ";
    33     }
    34     cout << endl;
    35     return 0;
    36 }
  • 相关阅读:
    方法和参数
    【转】priority_queue优先队列
    【转】主席树学习
    【转】树链剖分
    【转】线段树完全版~by NotOnlySuccess
    【转】树状数组
    【转】最大流EK算法
    【转】POJ题目分类推荐 (很好很有层次感)
    【转】原根
    【转】Polya定理
  • 原文地址:https://www.cnblogs.com/fx1998/p/12691947.html
Copyright © 2020-2023  润新知