[排列組合]Codeforces Round #324 (Div. 2)E
阿新 • • 發佈:2018-12-24
題意:
給出兩個序列p和s,問從p變化到s移動的最小距離是多少。
輸出最小距離,移動的次數和移動的點。
分析:
邏輯總是感覺很混亂,這裡把s的序列重新標號,那麼s就是1,2,3,。。n.也就是將p重新標號後的順序變化成有序遞增的序列。這樣邏輯上稍微清楚些。然後就是貪心的思想,在將b[k]移動到b[k]的位置的時候所經過的大於b[k]的數都往後移。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <fstream>
#include <math.h>
#include <iomanip>
#define read freopen("q.in","r",stdin)
using namespace std;
typedef long long LL;
#define inf 0x3fffffff
typedef pair<int , int> pii;
const int maxn = 2003;
int mp[maxn];
int b[maxn],p[maxn];
int x[maxn*100],y[maxn*100];
int n;
int main()
{
//read;
int i,j,k,a,cnt=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
}
for(i=1;i<=n;i++)
{
scanf("%d",&a);
mp[a]=i;
}
for (i=1;i<=n;i++)b[i]=mp[p[i]];
int res=0;
for(i=1;i<=n;i++)
{
// cout<<"EEEE"<<endl;
for(k=i;;k++)if(b[k]==i)break; //找出i點應該填的數的位置
while(i!=k)
{
for(j=i;j<=k;j++)
{
if(b[j]>=k)
{
swap(b[j],b[k]);
x[cnt]=j;
y[cnt++]=k;
res+=k-j;
k=j; //交換後,k的位置改變,繼續移動
}
}
}
}
printf("%d\n%d\n",res,cnt);
for(i=0;i<cnt;i++)printf("%d %d\n",x[i],y[i]);
}