zoukankan      html  css  js  c++  java
  • codeforces 584E Anton and Ira [想法题]

    题意简述:

    给定一个$1$到$n(n<=2000)$的初始排列以及最终排列 我们每次可以选取位置为$i$和$j$的

    并交换它们的位置 花费为$ |i-j| $ 求从初始状态变换到末状态所需最小花费

    -----------------------------------------------------------------------------------------------------------

    比赛时这题留了$40min$ 然而自己贪心策略还是有漏洞

    结束后看了首页的官方题解 感觉思路非常值得借鉴

    首先 我们把末状态变为到$1~n $初状态也与之相对应地改变 (设为$a[i]$)

    比如样例可以变为

    $3 2 4 1$

    $1 2 3 4$

    我们假设每次交换花费为$ 2|i-j| $那么从初始状态到末状态最优的情况下花费即为 

    $sum_{i}^{n}|a[i]-i|$

    -----------------------------------------------------------------------------------------------------------

    已经知道问题的下界了 我们再来考虑是否对于任意情况 总存在一种达到下界花费的方案

    我们每次考虑当前状态中值最小且不在对应位置的数 然后找它左边第一个比它位置大的数

    然后进行交换 直到它换到自己的目标位置

    我们会发现 按照这样的换法 所有数都一直在向着目标位置移动 没有往返过

    所以花费就是最小的 即 $sum_{i}^{n}|a[i]-i|$

    另外由于交换次数给的范围比较大 $(n^{2}/2)$ 刚好是比极限情况($n$到$1$排列)稍大

    于是这题做到这里就可以解决了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=2010;
    int a[N],pos[N];
    int ans1[N*N>>1],ans2[N*N>>1];
    int n,k,ans;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        int x;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&x);
            pos[x]=i;
        }
        for(int i=1;i<=n;++i)
            a[i]=pos[a[i]];
        for(int i=1;i<=n;++i)
        {
            int j=i;
            while(a[j]!=i)
                ++j;
            while(j!=i)
            {
                int l=j-1;
                while(a[l]<j)
                    --l;
                ans+=j-l;
                ++k;
                ans1[k]=l;
                ans2[k]=j;
                swap(a[l],a[j]);
                j=l;
            }
        }
        printf("%d
    %d
    ",ans,k);
        for(int i=1;i<=k;++i)
            printf("%d %d
    ",ans1[i],ans2[i]);
        return 0;
    }
  • 相关阅读:
    SpringSecurity 3.2入门(8)自定义权限控制数据库设计
    SpringSecurity 3.2入门(7)自定义权限控制介绍
    SpringSecurity 3.2入门(6)简单介绍默认使用的十一个过滤器
    Spring3.2下使用JavaMailSenderImpl类发送邮件
    Java Mail邮件发送的简单实现
    Spring下配置几种常用连接池
    23种设计模式入门之工厂模式
    C# BackgroundWorker的Bug???
    C# BeginInvoke和EndInvoke方法
    c# 高效的线程安全队列ConcurrentQueue
  • 原文地址:https://www.cnblogs.com/sagitta/p/4858692.html
Copyright © 2011-2022 走看看