zoukankan      html  css  js  c++  java
  • 置换的一项运用 poj3270

      关于置换,就是建立起映射关系。

      题目链接:http://poj.org/problem?id=3270

      题目大意:要求将每头牛从大到小排序,但是牛有怒气值,每移动两头牛,就需要付出这两头牛的怒气值作为代价。问,最小的怒气值是多少。

      在样例中建立起映射关系。

      

    联想到数学里面的有关群的问题。使用最小的数去加途中经历过的牛的怒气值。

    但是在遇到,最小的怒气值不在循环里面的时候, 最优解是不会根据上面的方法实现的。

    例如:

    根据上面的方法,得到的解为42。

    而如果调用一下1去跟后面的循环去换,得到的解为41。

    显然,可以根据最小值去得到最优解。

    于是有两种方法:

    第一种直接调用循环节里面的最小值,去跟循环里面的元素交换。

    sum1=(minl+L(1))+(minl+L(2))+.......+(minl+L(m-1)) 

    其中,设X为循环节的所有元素的集合,则L为X中除去最小值后的子集。minl为X集合中的最小值。

    整理得:sum1=minl*(m-1)+sum(L)*(m-1)       其中sum(L) 为集合L的总和,minl为集合X的最小值。

     

    第二种方法,整个集合中的最小元素不在循环节中,但是借用整个集合的最小元素与循环节中的最小元素调换两次,求出的解。

    sum2=(min_all+X(1))+(min_all + X(2))+.......+(min_all + X(m)) +(min_all + minl)

    其中,min_all为整个集合中最小的元素(不在循环节内), X集合为循环节的所有元素,minl为X集合中的最小元素。

    整理得: sum2= min_all * (m+1) +sum(X) + minl

    最优的结果只需要找出这两种方法中的最小值即可。

     

    参考博客:https://www.cnblogs.com/kuangbin/archive/2012/09/03/2669013.html

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=10006;
     6 const int inf=0x3f3f3f3f;
     7 struct Point{
     8     int id,num;
     9     bool operator < (const Point b) const{
    10         return this -> num < b.num;
    11     }
    12 }cow[maxn];
    13 bool flag[maxn];
    14 int MAXN;
    15 
    16 int solve(int n)
    17 {
    18     int ans=0;
    19     memset( flag, 0, sizeof flag);
    20     for(int i=1;i<=n;i++){
    21         if(!flag[i]){
    22             flag[i]=true; ///用flag判断是否在循环节中
    23             int minl=cow[i].num;
    24             int sum1=cow[i].num;
    25             int next=cow[i].id;
    26             int quan=1;
    27             while(!flag[next]){
    28                 flag[next]=true;
    29                 quan++;
    30                 if(minl>cow[next].num) minl=cow[next].num;
    31                 sum1+=cow[next].num;
    32                 next=cow[next].id;
    33             }
    34             ans+=min( sum1-minl+(quan-1)*minl, sum1+minl+(quan+1)*MAXN); 
    35             ///在min的左边,计算结果为方法一。
    36             ///min的右边,计算结果为方法二。
    37         }
    38     }
    39     return ans;
    40 }
    41 
    42 int main()
    43 {
    44     ios_base::sync_with_stdio(0); cin.tie(0);
    45     cout.tie(0);
    46     int n;
    47     while( cin >> n){
    48         MAXN=inf;
    49         for(int i=1;i<=n;i++){
    50             cow[i].id=i;
    51             cin >> cow[i].num;
    52             if(MAXN>cow[i].num) MAXN=cow[i].num;
    53         }
    54         sort( cow+1, cow+1+n); ///排序之后即可建立起映射关系
    55         cout << solve(n) <<endl;
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    C#循环页面form中控件
    鼠标放到按钮上页面样式发生变化
    access INSERT INTO 语句的语法错误
    更改水晶报表数据源
    C# byte[]与string互转
    禁用右键
    showModalDialog IE9 报错
    ListBox 循环删除当前项
    showModalDialog 刷新本页面,不重新发送信息,则无法刷新网页,Page_PreRender
    敏捷模式开发(转)
  • 原文地址:https://www.cnblogs.com/ZQUACM-875180305/p/9049026.html
Copyright © 2011-2022 走看看