Processing math: 100%

Codeforces 584E - Anton and Ira - [贪心]

题目链接:https://codeforces.com/contest/584/problem/E

 

题意:

给两个 1n 的排列 p,s,交换 pi,pj 两个元素需要花费 |ij|,要求你用最少的钱交换 p 中的元素使得其变成 s

 

题解:

思路很简单,给个例子如下:

p5,1,2,3,4,6

s3,4,1,6,2,5

我们不难发现,像:

p5,1,2_,3_,4,6

s3_,4,1,6,2_,5

或者

p5,1,2_,3,4_,6

s3,4_,1,6,2_,5

这样的情况,交换两个数字必定是不会亏的,而且是必须要花费的,所以每次都直接暴力枚举找符合的 (i,j),一旦遇到就立刻把它俩交换即可。

当然不能太过暴力地 O(n2) 去找 (i,j),需要一点剪枝和区间控制。

 

AC代码:

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
#define mk(x,y) make_pair(x,y)
#define fi first
#define se second
const int maxn=2e3+10;
int n;
int s[maxn],t[maxn];
int pos[maxn];

P Find()
{
    int x,y;
    for(int i=1;i<=n;i++)
    {
        x=pos[s[i]];
        if(i<x)
        {
            for(int j=i+1;j<=x;j++)
            {
                y=pos[s[j]];
                if(y<=i) return mk(i,j);
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    for(int i=1;i<=n;i++) cin>>t[i], pos[t[i]]=i;

    int diff=0;
    for(int i=1;i<=n;i++) diff+=(s[i]!=t[i]);

    vector<P> op;
    int cost=0;
    while(diff)
    {
        P r=Find();
        swap(s[r.fi],s[r.se]);
        //printf("%d <-> %d\n",r.fi,r.se);
        op.push_back(r);
        cost+=abs(r.fi-r.se);
        diff-=(s[r.fi]==t[r.fi]);
        diff-=(s[r.se]==t[r.se]);
    }

    cout<<cost<<'\n';
    cout<<op.size()<<'\n';
    for(auto x:op) cout<<x.fi<<" "<<x.se<<'\n';
}
复制代码

 

posted @   Dilthey  阅读(191)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示