題目連接:https://codeforces.com/contest/584/problem/Eios
題意:c++
給兩個 $1 \sim n$ 的排列 $p,s$,交換 $p_i,p_j$ 兩個元素須要花費 $|i-j|$,要求你用最少的錢交換 $p$ 中的元素使得其變成 $s$。spa
題解:code
思路很簡單,給個例子以下:blog
$p$:$5,1,2,3,4,6$ci
$s$:$3,4,1,6,2,5$get
咱們不難發現,像:it
$p$:$5,1,\underline{2},\underline{3},4,6$io
$s$:$\underline{3},4,1,6,\underline{2},5$class
或者
$p$:$5,1,\underline{2},3,\underline{4},6$
$s$:$3,\underline{4},1,6,\underline{2},5$
這樣的狀況,交換兩個數字一定是不會虧的,並且是必需要花費的,因此每次都直接暴力枚舉找符合的 $(i,j)$,一旦遇到就馬上把它倆交換便可。
固然不能太過暴力地 $O(n^2)$ 去找 $(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'; }