Anton loves transforming one permutation into another one by swapping elements for money, and Ira doesn't like paying for stupid games. Help them obtain the required permutation by paying as little money as possible.
More formally, we have two permutations, p and s of numbers from 1 to n. We can swap pi and pj, by paying |i - j| coins for it. Find and print the smallest number of coins required to obtain permutation s from permutation p. Also print the sequence of swap operations at which we obtain a solution.
The first line contains a single number n (1 ≤ n ≤ 2000) — the length of the permutations.
The second line contains a sequence of n numbers from 1 to n — permutation p. Each number from 1 to n occurs exactly once in this line.
The third line contains a sequence of n numbers from 1 to n — permutation s. Each number from 1 to n occurs once in this line.
In the first line print the minimum number of coins that you need to spend to transform permutation p into permutation s.
In the second line print number k (0 ≤ k ≤ 2·106) — the number of operations needed to get the solution.
In the next k lines print the operations. Each line must contain two numbers i and j (1 ≤ i, j ≤ n, i ≠ j), which means that you need to swap pi and pj.
It is guaranteed that the solution exists.
4 4 2 1 3 3 2 4 1
3 2 4 3 3 1
In the first sample test we swap numbers on positions 3 and 4 and permutation p becomes 4 2 3 1. We pay |3 - 4| = 1 coins for that. On second turn we swap numbers on positions 1 and 3 and get permutation 3241 equal to s. We pay |3 - 1| = 2 coins for that. In total we pay three coins.
好题!
题目大意,给两个数列,x,和y,每交换一次x的代价是|i-j|,问花费最少将x变成y需要几步,代价一共多少,分别是哪几步?
方法:先通过映射,将Y转换为1 2 3 4 ....正序序列,再用映射关系把X也对应转换,然后yy一个结论
例如样例的数据
将3 2 4 1映射成1 2 3 4
则f(3)=1,f(2)=2,f(4)=3,f(1)=4;
则X序列此时就变成3 2 4 1
那把 3 2 4 1通过交换变成 1 2 3 4的代价结果和样例中所求的答案是相同的
然后是结论:
越大的数,应当是放在越靠后的位置的
for循环i从最大的开始,遇到正确的位置数i==x[i]的就跳过
每次找到X当前数中==最大数的位置
把这个位置pos记下来,因为要处理的就是这个位置的数,目的就是将这个位置的数变成X[i].
然后找到哪里去交换这个pos位置的数
其实很简单,就是贪心
for循环从j=pos+1的位置开始找,保证后面X数的位置j一定比当前要处理的数的位置pos要大,显然.
那为了代价最小,就优先让在j后面位置的但不大于pos位置数(也就是小于等于我们要处理的那个数)和pos位置交换
因为pos的数是当前最大的,早晚都是要滚去最后面的。
所以他pos后面的数都应当排在pos前面
交换后将代价累加即可,保存交换的两个位置即可
#include <stdio.h>
#include <algorithm>
using namespace std;
const int MAXN=2005;
int x[MAXN];
int y[MAXN];
int f[MAXN];
int ansi[MAXN*MAXN];
int ansj[MAXN*MAXN];
int main()
{
int n,cnt=0,sum=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&y[i]);
f[y[i]]=i;
}
for(int i=1;i<=n;i++)
x[i]=f[x[i]];
for(int i=n;i>=1;i--)
{
if(x[i]==i)
continue;
int pos;
for(int j = 1; j <= n; j++)
{
if(x[j] == i)
{
pos = j;
break;
}
}
int j=pos+1;
for(int j=pos+1;pos!=i;j++)
{
if(pos>=x[j])
{
ansi[cnt]=pos;
ansj[cnt++]=j;
sum+=(j-pos);
swap(x[pos],x[j]);
pos=j;
j--;
}
}
}
printf("%d\n%d\n",sum,cnt);
for(int i=0;i<cnt;i++)
printf("%d %d\n",ansi[i],ansj[i]);
return 0;
}