zoukankan      html  css  js  c++  java
  • 数学:置换群-轮换计数(1)

    BZOJ1697:置换群的轮换计数

    把牛排序,只能每次交换两个牛的位置,代价为这两个牛的脾气之和

    问最小交换代价

    交换的原始序列是输入序列,目标序列是有序的序列

    我们求出每一个轮换,记录每一个轮换的信息,考虑两种情况然后计数就可以了

     1 //对于其中一个循环
     2 //sum + (len – 2) * min 
     3 //sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字
     4 
     5 //sum + min + (len + 1) * smallest
     6 //sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字,smallest是整个数列最小的数字
     7 #include<cstdio>
     8 #include<algorithm>
     9 #include<cstring>
    10 #define INF 0x7f7f7f7f
    11 using namespace std;
    12 const int maxn=10005;
    13 int n,vmin,cnt,ans;
    14 int v[maxn],dis[maxn],vis[maxn],len[maxn],sum[maxn],id[maxn],mn[maxn];
    15 int read()
    16 {
    17     int x=0,f=1;char ch=getchar();
    18     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    19     while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    20     return x*f;
    21 }
    22 int find(int x)  //有序,二分查找x的最终位置 
    23 {
    24     int l=1,r=n;
    25     while(l<=r)
    26     {
    27         int mid=(l+r)>>1;
    28         if(dis[mid]>x) r=mid-1;
    29         else if(dis[mid]==x) return mid;
    30         else l=mid+1;
    31     }
    32     return -1;
    33 }
    34 void solve(int x)  //处理轮换 
    35 {
    36     vis[x]=1;cnt++;
    37     len[cnt]=1;sum[cnt]+=v[x];mn[cnt]=min(mn[cnt],v[x]); 
    38     int now=x;
    39     while(v[id[now]]!=v[x])
    40     {
    41         now=id[now];vis[now]=1;
    42         len[cnt]++;sum[cnt]+=v[now];mn[cnt]=min(mn[cnt],v[now]);
    43     }
    44 }
    45 void init()
    46 {
    47     vmin=INF;
    48     memset(mn,127/3,sizeof(mn));
    49 }
    50 int main()
    51 {
    52     init();
    53     n=read();
    54     for(int i=1;i<=n;i++)
    55     {
    56         v[i]=read();
    57         dis[i]=v[i];
    58         vmin=min(vmin,v[i]);
    59     }
    60     sort(dis+1,dis+n+1);
    61     for(int i=1;i<=n;i++) id[i]=find(v[i]);  //id每一个元素的最终位置 
    62     for(int i=1;i<=n;i++)
    63     if(!vis[i]&&i!=id[i]) solve(i);
    64     for(int i=1;i<=cnt;i++)
    65     {
    66         int t1=(len[i]-2)*mn[i];
    67         int t2=mn[i]+(len[i]+1)*vmin;
    68         ans+=sum[i]+min(t1,t2);
    69     } 
    70     printf("%d",ans);
    71     return 0;
    72 }
  • 相关阅读:
    Repository中进行模糊查询
    Spring jpa添加查询条件
    java后端repository层中进行模糊查询
    MyBatis小白问题 1、Invalid bound statement (not found): com.itheima.dao.UserDao.findAll,2、Resources.getResourceAsStream()报错
    Date类型做加减运算
    时间格式转换
    mysql-支持的数据类型
    mysql—表的完整性约束
    数据库—表操作(第二章)
    mysql—使用python操作mysql数据库(第五章)
  • 原文地址:https://www.cnblogs.com/aininot260/p/9695885.html
Copyright © 2011-2022 走看看