| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1849 人关注过本帖, 1 人收藏
标题:我也来发个求排列的题
只看楼主 加入收藏
草狼
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:2
帖 子:577
专家分:1040
注 册:2010-4-6
收藏
得分:0 
回复 29楼 beyondyf
没提交地址的 自己想的呵呵
你的想法完全正确的, 我就是看到那个置顶贴
然后想到了一个算法 然后就出了这题, 嘿嘿
2012-06-01 19:40
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
搞定。可惜没处提交。
程序代码:
#include<stdio.h>

#define    FACT_MAX    20

long long F[FACT_MAX + 1];

long long permutation_to_number(int * p, int len)
{
    int i, j, c;
    long long sum;
    for(sum = i = 0; i < len; sum += c * F[len - 1 - i++])
    for(c = 0, j = i + 1; j < len; j++)
        if(p[i] > p[j]) c++;
    return sum;
}

void number_to_permutation(long long num, int len, int * p)
{
    int i, j, t;
    num %= F[len--];
    for(i = 0; i <= len; i++) p[i] = i + 1;
    for(i = 0; num; i++)
    {
        j = i + num / F[len - i];
        for(t = p[j]; j > i; j--)
            p[j] = p[j - 1];
        p[i] = t;
        num %= F[len - i];
    }
}

int main()
{
    int p[24], m, n, i;
    long long k;
    for(F[0] = i = 1; i <= FACT_MAX; i++) F[i] = F[i - 1] * i;
    for(scanf("%d", &m); m--; puts(""))
    {
        scanf("%d%I64d", &n, &k);
        for(i = 0; i < n; scanf("%d", &p[i++]));
        k += permutation_to_number(p, n);
        number_to_permutation(k, n, p);
        for(printf("%d", p[0]), i = 1; i < n; printf(" %d", p[i++]));
    }
    return 0;
}

重剑无锋,大巧不工
2012-06-01 19:45
草狼
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:2
帖 子:577
专家分:1040
注 册:2010-4-6
收藏
得分:0 
回复 32楼 beyondyf
应该行吧, 反正跟我的程序运行出来的结果都一样的

我就当我们的程序时正确的吧 来给几组测试案列
输入:
5
19 121645100408832000
1 2 3 6 5 4 7 8 9 10 11 12 13 14 15 16 17 18 19
19 12164510040883   
1 2 3 6 5 4 7 8 9 10 11 12 13 14 15 16 17 18 19
19 121645
1 2 3 15 9 12 11 13 14 18 10 17 4 8 6 19 5 16 7
19 121645
1 2 3 15 9 12 11 13 14 18 19 16 5 8 4 7 10 6 17
19 3548219999110011323
19 10 2 18 11 15 1 16 9 17 8 12 6 14 13 5 7 3 4
输出:
1 2 3 6 5 4 7 8 9 10 11 12 13 14 15 16 17 18 19
1 2 3 15 9 12 11 13 14 18 10 17 4 8 6 19 5 16 7
1 2 3 15 9 12 11 13 14 18 19 16 5 8 4 7 10 6 17
1 2 3 15 9 12 11 13 14 19 6 17 7 8 16 18 5 10 4
3 14 16 7 10 15 2 19 13 1 5 12 6 18 11 4 9 17 8


我的代码: 主要思想就是康托展开和康托展开逆运算
程序代码:
#include<iostream>
using namespace std;

long long f[21] = {0,1,2};

long long cantor(int num[], int len) 
{
    long long sum = 0;
    for(int i=0; i<len; ++i) {
        int tmp = 0;
        for(int j=i+1; j<len; ++j)
            if(num[i] > num[j])
                tmp++;
        sum += f[len-i-1]*tmp;
    }
    return sum+1;
}

void uncantor(int num[], long long k, int len)
{
    int flag[30] = {0};
    for(int i=len-1; i>0; --i) {
        long long tmp = k / f[i];
        k = k % f[i];
        int j;
        for( j=1; j<=len; ++j) {
            if(flag[j]) continue;
            if( tmp == 0) break;
            tmp--;
        }
        
        num[len-i-1] = j;
        flag[j] = 1;
    }
    for(int i=1; i<=len; ++i)
        if( !flag[i] ) {
            num[len-1] = i;
            break;
        }
}

int main()
{
    int k;
    for(int i=3; i<=20; ++i)
        f[i] = f[i-1] * i;

    cout << f[19] << endl;
    while( cin >> k ) {
        while( k-- ) {
            long long n,m;
            cin >> n >> m;

            int num[30];
            for(int i=0; i<n; ++i) 
                cin >> num[i];

            long long cnt = cantor(num, n);
            if( (cnt + m) % f[n] ) m =(cnt+m) %f[n];
            else m =f[n];
            uncantor(num, m-1, n);

            cout << num[0];
            for(int i=1; i<n; ++i)
                cout << " " << num[i];
            cout << endl;
        }
    }
    return 0;
}
2012-06-01 20:00
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
唉,找出错误了,,有个地方有个bug,修改后虽然对了,但代码看起来太不河蟹了,,就不贴了
2012-06-01 20:07
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
本来今天想取消那个贴子的置顶的。既然大家的参与热情这么高,那就连这一贴也置顶一段时间吧。

重剑无锋,大巧不工
2012-06-01 20:09
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 33楼 草狼
看了一下这个代码,是不是就是首先算出目前的排列是第几个,然后加上m,最后用反的方法推出目标排列?
2012-06-01 20:10
草狼
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:2
帖 子:577
专家分:1040
注 册:2010-4-6
收藏
得分:0 
回复 36楼 czz5242199
恩, 其实就是个数学题, 哈哈
2012-06-01 20:12
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:2 
现在的 oj 题动不动就是 long long 吗?
2012-06-01 23:10
青春无限
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江苏
等 级:贵宾
威 望:24
帖 子:3451
专家分:19340
注 册:2012-3-31
收藏
得分:2 
hh

学 会看代码…学习写程序…学会搞开发…我的目标!呵呵是不是说大话啊!!一切皆可能
2012-06-02 00:41
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
回复 38楼 pangding
俺的VC6不支持long long / __int64 你们的程序都要到VS2010下去看 。

梅尚程荀
马谭杨奚







                                                       
2012-06-02 09:53
快速回复:我也来发个求排列的题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.030776 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved