zoukankan      html  css  js  c++  java
  • POJ 3270 Cow Sorting 置换群

    Cow Sorting

    接触到置换群的概念,对于一个(1~n)的一个排列a1, a2, a3...an

        1   2   3   4   5 ... n

       a1  a2 a3 a4 a5...an

    看作是一个置换,那么将其写为若干个不相交的循环的乘积形式(A1, A2, ... Ap1)(B1, B2, ... Bp2)... ...,例如

       1 2 3 4 5 6

       3 5 6 4 2 1

    可以写为(1 3 6)(2 5)(4)的形式,这里可以看成有3个循环(可以理解为上面的1 3 6这个集合,对应在下面也是 1 3 6)

    那么对应在每一个循环中,可以通过最多Ki - 1此交换使得这个循环有序,这里的Ki表示第i个循环的集合的大小。也就是说每交换一次可以使得一个元素回到自己的位置,由于交换的代价是这两个元素值的和,那么根据贪心的思想,每次选择用这个循环中的最小值将其他元素交换到对应的位置上去。那么总代价就是

    SUMi + (Ki - 2) * Mi

    这里Mi表示第i个循环的最小值,SUMi表示第i个循环的和,Ki表示这个循环的元素的个数。

    另外,从另一个角度出发,如果整个序列的最小值非常小,那么我们判断是不是可以先用整个序列的最小值把第i个循环的最小值Mi换出来,然后将这个集合(循环)交换到有序后,再将Mi交换回来,这样总代价就是

    SUMi + (Ki + 1) * MIN + Mi

    其中MIN表示整个序列的最小值。

    那么,最后的答案就是  ans = SIGMA{ SUMi + min{(Ki - 2) * Mi,  (Ki + 1) * MIN + Mi} }

     1 #pragma comment(linker, "/STACK:1677721600")
     2 #include <map>
     3 #include <set>
     4 #include <stack>
     5 #include <queue>
     6 #include <cmath>
     7 #include <ctime>
     8 #include <bitset>
     9 #include <vector>
    10 #include <cstdio>
    11 #include <cctype>
    12 #include <cstdarg>
    13 #include <cstring>
    14 #include <cstdlib>
    15 #include <iostream>
    16 #include <algorithm>
    17 using namespace std;
    18 #define INF 0x3f3f3f3f
    19 #define inf (-((LL)1<<40))
    20 #define root 1, 1, n
    21 #define middle ((L + R) >> 1)
    22 #define lson k<<1, L, (L + R)>>1
    23 #define rson k<<1|1,  ((L + R)>>1) + 1, R
    24 #define mem0(a) memset(a,0,sizeof(a))
    25 #define mem1(a) memset(a,-1,sizeof(a))
    26 #define mem(a, b) memset(a, b, sizeof(a))
    27 #define FIN freopen("in.txt", "r", stdin)
    28 #define FOUT freopen("out.txt", "w", stdout)
    29 #define rep(i, a, b) for(int i = a; i <= b; i ++)
    30 #define dec(i, a, b) for(int i = a; i >= b; i --)
    31 
    32 //typedef __int64 LL;
    33 typedef long long LL;
    34 typedef pair<int, int> Pair;
    35 const int MAXN = 300000 + 10;
    36 const int MAXM = 1100000;
    37 const double eps = 1e-12;
    38 LL MOD = 1000000007;
    39 
    40 int n;
    41 struct Node {
    42     int a, id;
    43     bool operator < (const Node &A) const {
    44         return a < A.a;
    45     }
    46 }node[MAXN];
    47 bool vis[MAXN];
    48 
    49 int find_ans(int p, int &mi, int &cnt) {
    50     int sum = 0;
    51     mi = INF;
    52     cnt = 0;
    53     do {
    54         sum += node[p].a;
    55         vis[p] = 1;
    56         cnt ++;
    57         mi = min(mi, node[p].a);
    58         p = node[p].id;
    59     } while(!vis[p]);
    60     return sum;
    61 }
    62 
    63 int main()
    64 {
    65 #ifndef ONLINE_JUDGE
    66     FIN;// FOUT;
    67 #endif
    68     while(~scanf("%d", &n)) {
    69         int mi = INF;
    70         rep (i, 1, n) {
    71             scanf("%d", &node[i].a);
    72             node[i].id = i;
    73             mi = min(mi, node[i].a);
    74         }
    75         sort(node + 1, node + n + 1);
    76         mem0(vis);
    77         int cur_min, cur_cnt, ans = 0;
    78         rep (i, 1, n) if(!vis[i]) {
    79             int sum = find_ans(i, cur_min, cur_cnt); // 找到当前循环的元素个数,最小值
    80             if(cur_cnt > 1) {// mi表示所有数字中的最小值
    81                 ans += sum + min( (cur_cnt - 2) * cur_min, (cur_cnt + 1) * mi + cur_min );
    82             }
    83         }
    84         cout << ans << endl;
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    如何用Warkdowm来写一篇博客
    关于toString()的一些事情
    python的 range() 函数
    python中的split()函数
    innerHTML和value打架了?
    JS如何实现实时获取网络时间
    javascript内嵌样式与外联样式怎么做?
    c语言实现乘法口诀表
    c语言实现数字的倒序输出
    c语言解一元二次方程
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/4713330.html
Copyright © 2011-2022 走看看