POJ 3270 Cow Sorting

来源:互联网 发布:网络最新骗术 编辑:程序博客网 时间:2024/04/30 12:43

在做本题之前首先要对置换有所了解,众所周知对于一个循环内的元素需要交换循环长度减一次才能使得循环内的元素变成有序的,所以很自然的想法便是使一个置换的各个循环交换代价最少,便是最终的答案。最直观的想法是在一个循环中用该循环中的最小的元素去交换,便可使得交换代价最少,于是结果便是每个循环这样计算的结果的加和。提交1WA,然后看了discuss里面的一组数据(5     1 8 9 7 6),YY了一下,发现贪心的方法存在两种,一种是前面所说的那种,一种是对于每个循环内的最小的元素,首先和数组中最小的元素进行交换,然后用该最小的元素去使得该循环内的其余的元素归位,然后再交换回置换内最小元素和数列最小元素。因此每次求解循环的最小交换代价的时候,应该取这两者的最小值,2A。。。


#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 10010;const int INF = 0x3f3f3f3f;typedef long long ll;struct Node{    int id, val;    Node() {}    Node(int t_id, int t_val) : id(t_id), val(t_val) {}    friend bool operator < (const Node &p1, const Node &p2)    {        return p1.val < p2.val;    }}p[MAXN];bool visit[MAXN];ll ans; int n, min_val;int main(){    //freopen("aa.in", "r", stdin);    //freopen("bb.out", "w", stdout);    while(scanf("%d", &n) != EOF)    {        ans = 0; min_val = INF;        memset(visit, false, sizeof(visit));        for(int i = 1; i <= n; ++i)        {            scanf("%d", &p[i].val);            p[i].id = i;            min_val = min(min_val, p[i].val);        }        sort(p + 1, p + n + 1);        for(int i = 1; i <= n; ++i)        {            if(!visit[p[i].id])            {                int min_num = INF;                ll tmp = 0;                int cnt = 0;                int j = i;                while(!visit[p[j].id])                {                    min_num = min(p[j].val, min_num);                    tmp += p[j].val;                    cnt++;                    visit[p[j].id] = true;                    j = p[j].id;                }                tmp -= min_num;                if(2*(min_val+min_num)+(cnt-1)*min_val < (cnt-1)*min_num)                    ans += 2*(min_val+min_num)+(cnt-1)*min_val;                else                    ans += (cnt-1)*min_num;                ans += tmp;            }        }        cout << ans << endl;    }    return 0;}


原创粉丝点击