习题8-6 起重机(Crane,ACM/ICPC CERC2013,UVa1611)

来源:互联网 发布:linux发展前景 编辑:程序博客网 时间:2024/04/28 04:30

题目大意:通过一系列操作使一个1~n的序列变为升序,每次操作可以选一个长度为偶数的连续区间,交换前一半和后一半。

思路:从序列第一位开始,查找对应值(若为第一位则查找1,第二位查找2,以此类推)。若查找位置与查找到的值的位置相距长度为偶数,则以查找位置与查找到的值得位置的中心进行交换操作;若查找到的位置与查找到的值的位置相距长度为奇数,则以查找位置的后一位与查找到的值的位置的中心进行交换操作。如此不断循环,知道对应位置与对应值符合。

#include<bits/stdc++.h>using namespace std;int main(){    int t;    cin>>t;    while(t--)    {        int n,a[10005],sum=0,t;        vector<int> v;        cin>>n;        for(int i=1;i<=n;i++)            cin>>a[i];        for(int i=1;i<=n;i++)        {            if(a[i]==i) continue;            for(int j=i;j<=n;j++)            {                if(a[j]!=i) continue;                int f,x=j;                while(x>i)                {                    if((x-i)%2==1)                    {                        f=(x-i+1)/2;                        for(int k=0;k<f;k++)                        {                            t=a[i+k];a[i+k]=a[i+k+f];a[i+k+f]=t;                        }                        v.push_back(i);                        v.push_back(x);                        sum++;                        x-=f;                   }                    else if((x-i)%2==0)                   {                        f=(x-i)/2;                        for(int k=0;k<f;k++)                        {                            t=a[i+1+k];a[i+1+k]=a[i+1+k+f];a[i+1+k+f]=t;                        }                        v.push_back(i+1);                        v.push_back(x);                        sum++;                        x-=f;                   }                }            }        }        cout<<sum<<endl;        for(int i=0;i<v.size();i+=2)        {            cout<<v[i]<<" "<<v[i+1]<<endl;        }    }}



阅读全文
6 0
原创粉丝点击