• poj3270


    终于把这个很久以前拖下来的问题解决了

    回忆一下,最少相邻交换次数等于逆序对数

    这里求的是最少交换代价(非相邻元素也可以交换);

    先考虑最少交换次数这个问题

    首先把现在数列看成原数列{1,2,3……n}的一个置换

    根据置换的理论,每一个置换都能拆成唯一的互不相交的循环

    显然最小交换次数是在每个循环内部交换达成的

    在一个包含元素数位x的循环内,交换成原数列的最小次数显然为x-1

    最小交换次数就很明显了

    而这里求的是最小交换代价,显然循环内部每个元素都要交换一次(除了只含一个元素的循环)

    首先想到的是用每个循环内最小元素使循环内其他元素归位

    注意还有一种情况,我们可以把整个序列里的最小元素a和这个循环里最小的b交换,然后用元素a与循环内其他元素交换,最后再把

    a交换出循环(a和b交换)

    最小代价就是取这两种方法较小的那一个

     1 var a,b:array[0..10010] of longint;
     2     f:array[0..100010] of longint;
     3     v:array[0..100010] of boolean;
     4     t,x,max,i,n,s,ans:longint;
     5 
     6 function min(a,b:longint):longint;
     7   begin
     8     if a>b then exit(b) else exit(a);
     9   end;
    10 
    11 procedure dfs(x:longint);   //找循环
    12   begin
    13     v[x]:=true;
    14     ans:=ans+a[x];
    15     inc(s);
    16     if not v[b[x]] then dfs(b[x]);
    17   end;
    18 
    19 begin
    20   readln(n);
    21   for i:=1 to n do
    22   begin
    23     readln(x);
    24     if x>max then max:=x;
    25     f[x]:=i;
    26   end;
    27   for i:=1 to max do  
    28     if f[i]>0 then
    29     begin
    30       inc(t);
    31       b[f[i]]:=t;
    32       a[t]:=i;
    33     end;
    34 
    35   for i:=1 to n do
    36     if not v[i] then
    37     begin
    38       s:=0;
    39       dfs(i);
    40       ans:=ans+min((s-2)*a[i],(s+1)*a[1]+a[i]);
    41     end;
    42 
    43   writeln(ans);
    44 end.
    View Code
  • 相关阅读:
    操作符的详解
    一切皆对象
    对象导论
    mysql
    bootstrap学习
    素数筛选法
    python的urllib库
    是做应用还是搞算法?
    金山词霸笔试题目笔记
    双十一,更是技术的战争~~
  • 原文地址:https://www.cnblogs.com/phile/p/4473188.html
Copyright © 2020-2023  润新知