codeforces1455 D. Sequence and Swaps

昨天晚上巨困,就没有打,今天课间的时候就看了一下D题,发现好像可以瞎搞,于是吃完饭就写了一下,调过样例一次就A了qaq。

D. Sequence and Swaps

枚举+贪心
由于数据范围 n ≤ 500 n\leq500 n500,由此我们可以在 n 3 n^3 n3完成此题。

最后完成所有操作后,我们手中肯定还有一个数,我们考虑去枚举这个数。

最后手里的数一定不在最终的排列中,于是用一个数组b[]除了手中的数记录下来,不难发现只要排序一下这个所有数的位置确定了。

而且不难发现如果当前手中的数是 x x x,我们必须一次将他归位,于是就模拟操作,每次找出现在手中的数在b[]数组中的位置(注意重复的数只需要开一个st[]数组记录一下即可),然后看看能不能执行交换操作,把过程模拟一边,顺便记录次数。

模拟过程中,如果当前手中的数已经是枚举剩余的数之间跳出循环,如果不能交换说明不合法也直接跳出循环。

最后再判断一下是否满足条件即可。

时间复杂度 O ( n 3 ) O(n^3) O(n3)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=510;
int a[N],b[N],c[N];
bool st[N];
int main()
{
    
    
    IO;
    int T=1;
    cin>>T;
    while(T--)
    {
    
    
        int n,x;
        cin>>n>>x;
        for(int i=1;i<=n;i++) cin>>a[i];
        bool fl=1;
        for(int i=2;i<=n;i++)//特判最后手中的数是 x 也就是不用操作
            if(a[i]<a[i-1]) fl=0;
        if(fl) 
        {
    
    
            cout<<0<<'\n';
            continue;
        }
        a[n+1]=x;
        int res=0x3f3f3f3f;
        for(int i=1;i<=n;i++)// 枚举剩下的数是a[i]
        {
    
    
            for(int j=1;j<=n;j++)
            {
    
    
                if(i==j)
                    b[j]=x;
                else
                    b[j]=a[j];
            }
            sort(b+1,b+1+n);
            
            int tmp=x;
            memcpy(c,a,sizeof c);

            bool ok=1;
            int cnt=0;
            for(int j=1;j<=n;j++)
            {
    
    
                memset(st,0,sizeof st);
                int k;
                for(k=1;k<=n;k++)// 找到当前手中的数应该所在的位置
                {
    
    
                    if(b[k]==tmp&&c[k]!=tmp)
                    {
    
    
                        while(st[k]||c[k]==tmp) k++;
                        st[k]=1;
                        break;
                    }
                }
            
                if(c[k]>tmp) // 能不能执行交换操作
                {
    
    
                    swap(c[k],tmp);
                    cnt++;
                    if(tmp==a[i]) break;//手中的数已经是枚举的数
                }
                else// 交换失败
                {
    
    
                    ok=0;
                    break;
                }
            }
            for(int i=2;i<=n;i++)
                if(c[i]<c[i-1]) ok=0;
            if(a[i]!=tmp) ok=0;// 最后手中的数tmp一定要等于枚举的数a[i]
            if(ok) res=min(res,cnt);
        }
        if(res==0x3f3f3f3f) cout<<-1<<'\n';
        else cout<<res<<'\n';
    }
    return 0;
}

感觉应该有复杂度更优的做法,但是我这个做法若优化感觉十分难写~~

要加油哦~

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/110428300