codeforces#324(div2) E. Anton and Ira 贪心
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.
题意:给两个1~n的序列,将序列p通过k次交换变成序列s,每次交换的代价为|i-j|,求最小交换代价,输出交换方案。
思路:本来看到1~n,应该想到置换,不过这题和置换并没有什么关系。。。
基本思路是这样,将一个数通过交换到达它该去的位置的过程中无论交换方式如何,代价是不变的。比如4 5 1 2 3,4要到达2所在的位置那么swap(1,3)+swap(3,4)=swap(1,2)+swap(2,4)(代价相等),但是相同的代价不同的交换方式造成的结果是不一样的,swap(1,3)使1更接近原位置了,swap(1,2)却使5偏离更原位置了,因此贪心出现在这里,我们要使在把每个数移动到它的位置时使得其它数更接近它的原位置,也就是对于每个能往右移动的,在移到原位置的途中把能往左移动也移动。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=(1<<29); int n; int p[maxn],s[maxn]; int id[maxn]; int cost; struct Node { int x,y; }; vector<Node> ans; int solve(int *a,int n) { if(n==1) return 0; int x,y; REP(i,1,n){ if(a[i]==n){ x=i;break; } } int cost=0; REP(i,x+1,n){ if(a[i]<=x){ ans.push_back({x,i}); swap(a[x],a[i]); cost+=abs(x-i); x=i; } } return cost+solve(a,n-1); } int main() { while(cin>>n){ ans.clear(); REP(i,1,n) scanf("%d",&p[i]); REP(i,1,n) scanf("%d",&s[i]),id[s[i]]=i; REP(i,1,n) p[i]=id[p[i]]; //REP(i,1,n) cout<<p[i]<<" ";cout<<endl; cost=solve(p,n); printf("%d %d ",cost,(int)ans.size()); for(int i=0;i<ans.size();i++) printf("%d %d ",ans[i].x,ans[i].y); } return 0; }