Codeforces 584E - Anton and Ira - [贪心]
题目链接:https://codeforces.com/contest/584/problem/E
题意:
给两个 1∼n 的排列 p,s,交换 pi,pj 两个元素需要花费 |i−j|,要求你用最少的钱交换 p 中的元素使得其变成 s。
题解:
思路很简单,给个例子如下:
p:5,1,2,3,4,6
s:3,4,1,6,2,5
我们不难发现,像:
p:5,1,2_,3_,4,6
s:3_,4,1,6,2_,5
或者
p:5,1,2_,3,4_,6
s:3,4_,1,6,2_,5
这样的情况,交换两个数字必定是不会亏的,而且是必须要花费的,所以每次都直接暴力枚举找符合的 (i,j),一旦遇到就立刻把它俩交换即可。
当然不能太过暴力地 O(n2) 去找 (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'; }
转载请注明出处:https://dilthey.cnblogs.com/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步