欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CodeForces - 1256B Minimize the Permutation(思维模拟)

程序员文章站 2022-06-02 22:17:28
...

题目链接https://vjudge.net/contest/341054#problem/B
CodeForces - 1256B Minimize the Permutation(思维模拟)
CodeForces - 1256B Minimize the Permutation(思维模拟)
解析
长度为n的一个排列(这个排列为n个数,从1到n)
最多进行n-1次操作
对于第i次操作,可以交换i和i+1位置上的数字
每一个位置交换后,就不能再进行交换了。
保证进行若干次操作后,能有最小的排列。输出这个最小的排列。
分析
首先明白长度相同的两个序列,Note中的解释很好的说明了如何判定排列p和q的大小
思想就是贪心先把最小的数字移到第一位,再移动次小的数字,以此类推。。。
举例:序列 5 4 1 3 2
先把数字1移动到第一位,得到序列1 5 4 3 2,此时i=2和i=1的位置已经移动过
再考虑把数字2往前移,得到序列1 5 2 4 3,此时i=4和i=3的位置也被移动过
把数字1和2移动过后,所有的位置都被移动过了,已经不能再进行移动
所以最小的序列就是1 5 2 4 3
此题时间有限制,必须得考虑到位,刚开始我是考虑

  for(int i=1; i<=n; i++)
        {
            for(int j=v; j<=n; j++)
            {
                if(a[j]==i)/*找到i的位置,但不是和本身一一对应*/
                {
                    int k=j;
                    while(num>0&&k>v)
                    {
                        if(book[k-1])
                            continue;
                        if(a[k-1]<a[k])
                            break;
                        swap(a[k-1],a[k]);
                        book[k-1]=1;
                        num--;
                        if(num==0)
                        {
                            flag=1;
                            break;
                        }
                        k--;
                    }
                    v++;
                    break;
                }
            }
            if(flag)
                break;
        }

对于两层for循环,从小到大遍历每一个元素,并找到此元素在其序列中的位置,然后对于没有交换过的位置进行交换,并对num的值进行–。其实对于num的判断是可以直接放在外边的。
正确代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e2+10;
int n,a[N],book[N];
int main()
{
    int q;
    scanf("%d",&q);
    while(q--)
    {
        memset(book,0,sizeof(book));
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        int num=n-1,k=1;
        while(k<=n&&num>0)
        {
            for(int i=1; i<=n; i++)
            {
                if(a[i]==k)/*找到元素k在其序列中的位置*/
                {
                    for(int j=i-1; j>=k; j--)
                    {
                        if(book[j])
                            continue;
                        if(a[j]<a[j+1])
                            break;
                        //对于这个for循环,结束条件就是a[j]<a[j+1],
                        //这个地方与num的值是无关的,因为每个位置最多就会被移动一次,移动过的位置会被直接跳过去
                        swap(a[j],a[j+1]);
                        book[j]=1;
                        num--;
                    }
                    k++;/*不管是否是按顺序移动位1 2 。。。n,k都要++*/
                    break;
                }
            }
        }
        for(int i=1; i<=n; i++)
            printf("%d ",a[i]);
        printf("\n");
    }
    return 0;
}

CodeForces - 1256B Minimize the Permutation(思维模拟)