zoukankan      html  css  js  c++  java
  • [Swust OJ 541]--排列字典序问题

    题目链接:http://acm.swust.edu.cn/problem/0541/

    Time limit(ms): 2000      Memory limit(kb): 65535

    n个元素{1,2,..., n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下: 


    0       1     2    3     4    5


    123 132 213 231 312 321


    任务:给定n 以及n 个元素{1,2,..., n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。

    Description

    第1 行是元素个数n(n < 15)。接下来的1 行是n个元素{1,2,..., n }的一个排列。

    Input

    第一行是字典序值,第2行是按字典序排列的下一个排列。

    Output
    1
    2
    8
    2 6 4 5 8 1 7 3
    Sample Input
    1
    2
    8227
    2 6 4 5 8 3 1 7
    Sample Output
     
     
    解题思路:两部曲(咳咳~~)
    一题目例子为例

    比2小的数有1个,则 tot+=1*7!;

    比6小的数有4个,则 tot+=4*6!;

    比4小的数有2个,则 tot+=2*5!;

    比5小的数有2个,则 tot+=2*4!;

    比8小的数有3个,则 tot+=3*3!;

    比1小的数有0个,则 tot+=0*2!;

    比7小的数有1个,则 tot+=1*1!;

    比3小的数没有;

    在实际求解中可以通过减去前面比当前数小的数来确定后面当前数小的数(方便程序的编写)
     
    对于求下一个序列,冲最后找,找到一个比最后一个数小的数把最后一个数放在之前就可以了
    当然懒人嘛(比如说我)就next_permutation()你值得拥有~~~
     
    代码如下
     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 int main()
     5 {
     6     int n, i, j, k, t, *p, x[16];
     7     x[0] = 1;
     8     for (i = 1; i < 15; i++)
     9         x[i] = x[i - 1] * i;
    10     while (cin >> n)
    11     {
    12         k = 0;
    13         p = new int[n + 1];
    14         for (i = 0; i < n; i++)
    15             cin >> p[i];
    16         for (i = 0; i < n - 1; i++)
    17         {
    18             t = p[i] - 1;
    19             for (j = 0; j < i; j++)
    20             if (p[j] < p[i])
    21                 t--;
    22             k += t*x[n - i - 1];
    23         }
    24         cout << k << endl;
    25         next_permutation(p, p + n);
    26         for (i = 0; i < n; i++)
    27             cout << p[i] << ' ';
    28         cout << endl;
    29     }
    30     return 0;
    31 }
    View Code
     用数位dp还是超时了(其实就这个状态设计本身来说不超时才是怪事,不想多说),代码先放在这里
     1 /*******************数位dp*************************/
     2 #include <iostream>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int n, bit[11], vis[10], flag;
     7 char s[11];
     8 
     9 int dfs(int pos, bool limit){
    10     if (pos >= n) return 1;
    11     int last = limit ? bit[pos] : n;
    12     int ret = 0;
    13     for (int i = 1; i <= last; i++){
    14         if (vis[i]) continue;
    15         vis[i] = 1;
    16         ret += dfs(pos + 1, limit&&i == last);
    17         vis[i] = 0;
    18     }
    19     return ret;
    20 }
    21 
    22 int main(){
    23     cin >> n;
    24     for (int i = 0; i < n; i++) cin >> bit[i];
    25     cout << dfs(0, 1) - 1 << endl;
    26     next_permutation(bit, bit + n);
    27     for (int i = 0; i < n; i++)
    28         cout << bit[i] << ' ';
    29     cout << endl;
    30     return 0;
    31 }
    View Code
  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4563936.html
Copyright © 2011-2022 走看看