题目:http://codeforces.com/contest/584/problem/E
题意:给定两个排列p1和p2。可以交换p1中的两个元素p1[i],p1[j],花费为|i-j|,求最小的话费使得p1变为p2。
分析:记p1[i]在p2中的位置为pos1,p1[j]在p2中的位置为pos2,要把p1[i]放到pos1位置,很明显,当pos1<=j而且po2<=i时p1[i]与p2[j]交换的性价比最高。然后3层循环枚举,一直交换,直到某个时刻数组扫了一遍没有元素交换,那么p1就变成了p2。
ps:居然过了。。。
代码:
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn = 3000;
int a[maxn],b[maxn];
int mp[3000000];
struct node
{
int x,y;
node()=default;
node(int a,int b)
:x(a),y(b){}
}s[3000000];
int Abs(int x)
{
if(x<0)
return -x;
return x;
}
int main()
{
int n,i,j,p=0,ans=0;
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
{
cin>>b[i];
mp[b[i]]=i;
}
int cur,temp;
while(true)
{
int fg2=0;
for(i=1;i<=n;i++)
{
temp=mp[a[i]];
if(temp==i)
continue ;
int cur=i,goal=temp;
while(cur<goal)
{
int fg1=0;
for(j=cur+1;j<=n && j<=goal;j++)
{
temp=mp[a[j]];
if(temp<=cur)
{
ans+=Abs(cur-j);
s[p++]=node(cur,j);
swap(a[cur],a[j]);
cur=j;
fg2=fg1=1;
break;
}
}
if(!fg1)
break;
}
}
if(!fg2)
break;
}
printf("%d\n",ans);
printf("%d\n",p);
for(i=0;i<p;i++)
printf("%d %d\n",s[i].x,s[i].y);
return 0;
}