• 1622: 排序工作量之新任务


    1622: 排序工作量之新任务

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 33  解决: 17
    [提交][状态][讨论版]

    题目描述

    假设我们将序列中第i件物品的参数定义为Ai,那么排序就是指将A1,…,An从小到大排序。若 i < j 且 Ai > Aj,则 < i , j > 就为一个“逆序对”。SORT公司是一个专门为用户提供排序服务的公司,他们的收费标准就是被要求排序物品的“逆序对”的个数,简称“逆序数”。Grant是这家公司的排序员,他想知道对于n个参数都不同的物品组成的序列集合中,逆序对数为t的物品序列有多少个,并试给出其中一个最小的物品序列。所谓 最小,即若有两个物品序列(A1,A2,…,An),(B1,B2,…,Bn),存在1≤i≤n,使得(A1,A2,…,Ai-1)=(B1,B2,…,Bi-1)且Ai<Bi。

    输入

    只有一行,该行只有两个整数n和t (1≤n≤20,0≤t≤n*(n-1)/2 )。

    输出

    有二行,第一行只有一个数,表示n个参数都不同的物品组成的序列集合中,逆序数为t的序列个数;第二行是所求物品参数序列。假设n个物品的参数分别为1到n。每个数字后面有一个空格,包括最后一个数字。

    样例输入

    4  3

    样例输出

    6
    1  4  3  2
    

    提示

     

    来源

    解析:

    第一小问动归解决;

    第二小问只交换相邻两数达到使逆序对只加一的目的。

    时间复杂度Otn

    #include<cstdio>

    #include<cstring>

    int i,j,k,n,t,p;

    longlong f[21][211];

    int ans[21];

    short rec[21];

    intswap(int &a, int &b)

    {

        int t=ans[a];

        ans[a]=ans[b];

        ans[b]=t;

    }

    intmain()

    {

        memset(f,0,sizeof(f));

        scanf("%d%d",&n,&t);

        if (n==1)

        {

            printf("1 1");

            return0;

        }

        f[2][1]=1; f[2][0]=1;

        for (i=3; i<=n; i++)

            for (j=0; j<=i*(i-1)/2; j++)

                for (k=0; k<i; k++)

                    if (j>=k)

                       f[i][j]+=f[i-1][j-k];                       

        printf("%lld ",f[n][t]);

        for (i=1; i<=n; i++)

          ans[i]=i;

        for (i=1; i<=t; i++)

        {

            memset(rec,0,sizeof(rec));

            p=n;

            rec[ans[p]]=p;

            while (rec[ans[p-1]+1] == 0) {p--; rec[ans[p]]=p;}

            int a=p-1,b=rec[ans[p-1]+1];

            swap(a,b);

        }

        for (i=1; i<=n; i++)

          printf("%d ",ans[i]);

        return0;

    }

    第一小问动归解决;

    第二小问只交换相邻两数达到使逆序对只加一的目的。

    时间复杂度Otn

    #include<cstdio>

    #include<cstring>

    int i,j,k,n,t,p;

    longlong f[21][211];

    int ans[21];

    short rec[21];

    intswap(int &a, int &b)

    {

        int t=ans[a];

        ans[a]=ans[b];

        ans[b]=t;

    }

    intmain()

    {

        memset(f,0,sizeof(f));

        scanf("%d%d",&n,&t);

        if (n==1)

        {

            printf("1 1");

            return0;

        }

        f[2][1]=1; f[2][0]=1;

        for (i=3; i<=n; i++)

            for (j=0; j<=i*(i-1)/2; j++)

                for (k=0; k<i; k++)

                    if (j>=k)

                       f[i][j]+=f[i-1][j-k];                       

        printf("%lld ",f[n][t]);

        for (i=1; i<=n; i++)

          ans[i]=i;

        for (i=1; i<=t; i++)

        {

            memset(rec,0,sizeof(rec));

            p=n;

            rec[ans[p]]=p;

            while (rec[ans[p-1]+1] == 0) {p--; rec[ans[p]]=p;}

            int a=p-1,b=rec[ans[p-1]+1];

            swap(a,b);

        }

        for (i=1; i<=n; i++)

          printf("%d ",ans[i]);

        return0;

    }

  • 相关阅读:
    8. Andr&#233;nalin ★ Serial
    1 Acid burn ★ Nag,Name/Serial,Serial
    【CPP】字符串和格式化输入输出
    什么是生成器
    【python密码学编程】8.使用换位加密法加密
    【python密码学编程】6.凯撒加密法
    【CPP】数据和C
    【python密码学编程】7.暴力破解凯撒加密法
    HDOJ 4515 小Q系列故事——世界上最遥远的距离
    POJ1131 Octal Fractions
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7775322.html
Copyright © 2020-2023  润新知