zoukankan      html  css  js  c++  java
  • 置换群 交换权值最小——pku3270

    题目的具体做法是参考刘汝佳的《算法艺术与信息学奥赛》,代码倒是自己实现的。大概思路是:
    1.找出初始状态和目标状态。明显,目标状态就是排序后的状态。
    2.画出置换群,在里面找循环。例如,数字是8 4 5 3 2 7
    明显,目标状态是2 3 4 5 7 8,能写为两个循环:
    (8 2 7)(4 3 5)。
    3.观察其中一个循环,明显地,要使交换代价最小,应该用循环里面最小的数字2,去与另外的两个数字,7与8交换。这样交换的代价是:
    sum - min + (len - 1) * min
    化简后为:
    sum + (len - 2) * min
    其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字。
    4.考虑到另外一种情况,我们可以从别的循环里面调一个数字,进入这个循环之中,使交换代价更小。例如初始状态:
    1 8 9 7 6
    可分解为两个循环:
    (1)(8 6 9 7),明显,第二个循环为(8 6 9 7),最小的数字为6。我们可以抽调整个数列最小的数字1进入这个循环。使第二个循环变为:(8 1 9 7)。让这个1完成任务后,再和6交换,让6重新回到循环之后。这样做的代价明显是:
    sum + min + (len + 1) * smallest
    其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字,smallest是整个数列最小的数字。
    5.因此,对一个循环的排序,其代价是sum - min + (len - 1) * min和sum + min + (len + 1) * smallest之中小的那个数字。

    View Code
    #include<stdio.h>
    #include
    <iostream>
    #include
    <algorithm>
    using namespace std;

    int hash[100009];
    int data1[10009];
    int t[10009];

    int main()

    {
    int n;
    int min;
    while(scanf("%d",&n)!=EOF)
    {
    int i;
    min
    =9999999;
    for(i=1;i<=100000;i++)
    hash[i]
    =0;
    for(i=1;i<=n;i++)
    {
    scanf(
    "%d",&data1[i]);
    if(min>data1[i])
    min
    =data1[i];
    hash[data1[i]]
    =1;
    }

    int add=1;
    for(i=1;i<=100000;i++)
    {
    if(hash[i]==1)
    {
    hash[i]
    =data1[add];
    add
    ++;
    if(add>n)
    break;
    }
    }
    //数据 放入hash

    int next,j;
    __int64 all
    =0;
    for(i=1;i<=100000;i++)
    {

    if(hash[i]!=0)
    {
    add
    =1;
    t[add]
    =hash[i];
    next
    =hash[i];
    add
    ++;
    hash[i]
    =0;
    while(hash[next]!=0)
    {
    t[add]
    =hash[next];
    int tn=next;
    next
    =hash[next];
    add
    ++;
    hash[tn]
    =0;
    }
    add
    --;

    if(add==1)continue;//置换群长度>=2
    //t[add]=hash[next];
    //add++;
    int he=0,sum1,sum2,qmin=9999999;
    for(j=1;j<=add;j++)
    {
    he
    +=t[j];
    if(qmin>t[j])
    qmin
    =t[j];
    }
    sum1
    =he+(add-2)*qmin;
    sum2
    =he+qmin+(add+1)*min;
    if(sum1>sum2)
    all
    +=sum2;
    else
    all
    +=sum1;
    }
    }

    printf(
    "%I64d\n",all);
    }
    }

  • 相关阅读:
    python封装configparser模块获取conf.ini值
    python(random模块)取10以内的随机数
    selenium-webdriver循环点击百度搜索结果以及获取新页面的handler
    xfire实现webservice客户端之测试关注点
    [译]36 Days of Web Testing(六)
    [译]36 Days of Web Testing(五)
    [译]36 Days of Web Testing(四)
    [译]36 Days of Web Testing(三)
    [译]36 Days of Web Testing(二)
    [译]36 Days of Web Testing(一)
  • 原文地址:https://www.cnblogs.com/huhuuu/p/2039382.html
Copyright © 2011-2022 走看看