当前位置: 首页 > news >正文

POJ 3270 置换群问题

题目大意是:

每头牛都有一个对应的值a[i],现在给定一个初始的牛的序列,希望通过两两交换,能够使这些牛按值升序排列,每次交换都会耗费一个 a[i]+a[j]

希望耗费最小,求出这个最小耗费

 

个人觉得这道题还是蛮有意思的,虽然我wa了很多发,但还是很值得思考一下的

 

这是一个置换群问题,但是我们首先要根据其值排个序确定每头牛本来应该属于的位置,再根据现在所在的位置得到一个映射关系to[i]

将a[i]又用b[]数组保存,排序后,b[i]表示第i大的牛的值

我们找出这个置换群中的所有循环集,每个循环集分别讨论,我们总是找到循环集中值最小的牛占据了别的牛的位置pos,然后把这个pos这个位置交换给对应的牛

这样得到的是b[min]+b[pos],因为每头牛总要回到自己的位置上,假定循环集中有len个牛,那么所有牛都回到自己的位置上那么所有的b[i]都要加一遍

但加的过程希望尽可能的小,所以总是跟b[min]相加,这个是可以保证的,因为在一个循环集中,每次交换最多只能令一个数回到正确位置上,除非到了最后一步

,否则的话,如果同时回到了正确位置,那么这两个数可以独立出来作为一个循环集,这与它们在原来的循环集中是矛盾的

 

其实到了这里感觉总的思路已经是对的

但是自己就是在这里wa了

想了半天发现还有更优的情况

另外还有一种情况需要考虑就是这个循环集中位置的交换可以利用b[1](也就是最小的牛)来帮忙

是不是通过利用最小编号的牛帮助这个循环集排好队是不是结果更小
最小的牛加进来帮忙就是值为b[1]的牛和当前循环集内最小的牛交换一次位置,帮好忙后再交换回来

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 10005;
 7 const int M = 100005;
 8 int a[N] , b[N] , to[N] , vis[N] , id[M];//to[]记录置换群上的映射关系
 9 
10 int circle(int u)
11 {
12     int v = u , ans = 0;
13     int cnt = 0;
14     while(u != to[v]){
15         vis[v] = 1;
16         cnt++;
17         ans = ans+b[v];
18         v = to[v];
19     }
20     ans = ans+b[v] , cnt++;
21     vis[v] = 1;
22     if(cnt == 1) return 0;
23     else{
24         /*这里要判断一下,是不是通过利用最小编号的牛帮助这个循环集排好队是不是结果更小
25         最小的牛加进来帮忙就是值为b[1]的牛和当前循环集内最小的牛交换一次位置,帮好忙后
26         再交换回来*/
27         int tmp = ans + b[u] + (cnt+1)*b[1];
28         return min(tmp , ans + (cnt-2)*b[u]);
29     }
30 }
31 
32 int main()
33 {
34   //  freopen("a.in" , "r" , stdin);
35     int n;
36     while(scanf("%d" , &n) != EOF)
37     {
38         for(int i=1 ; i<=n ; i++)
39         {
40             scanf("%d" , a+i);
41             b[i] = a[i];
42         }
43         sort(b+1 , b+n+1);
44         for(int i=1 ; i<=n ; i++)
45             id[b[i]] = i;
46         for(int i=1 ; i<=n ; i++)
47             to[i] = id[a[i]]; //表示第i个位置被第id[a[i]]大的牛占据了
48         memset(vis , 0 , sizeof(vis));
49         int ans = 0;
50         for(int i=1 ; i<=n ; i++)
51             if(!vis[i]) ans += circle(i);
52 
53         printf("%d\n" , ans);
54     }
55     return 0;
56 }

 

转载于:https://www.cnblogs.com/CSU3901130321/p/4242941.html

相关文章:

  • Amazon Aurora是如何设计原生云关系型数据库的?
  • mysql DEPENDENT SUBQUERY(转载)
  • 技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列
  • C#属性和字段
  • 记录一次自己对nginx+fastcgi(fpm)+mysql压力测试结果
  • 02 Redis关闭服务报错---(error) ERR Errors trying to SHUTDOWN. Check logs.
  • 近况
  • 微软亚洲研究院等提出CNN训练新方法RePr,准确率显著提升
  • 平时遇到一些问题的汇总收集(mvc)
  • 重要知识点:如何降低DNS***的风险
  • [转载]来个强悍的的吧 教你在Mac下隐藏文件,别做坏事哟
  • 多网卡捆绑bonding
  • 模块管理常规功能自己定义系统的设计与实现(53--演示程序和视频解说 )
  • 新一代视频AI服务,阿里云智能视觉重磅发布
  • 从代码看 asp.net 处理过程
  • 【译】JS基础算法脚本:字符串结尾
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • es6(二):字符串的扩展
  • Intervention/image 图片处理扩展包的安装和使用
  • magento 货币换算
  • mongo索引构建
  • mysql innodb 索引使用指南
  • Python十分钟制作属于你自己的个性logo
  • Spring Cloud Feign的两种使用姿势
  • SSH 免密登录
  • vue-router 实现分析
  • Yeoman_Bower_Grunt
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 仿天猫超市收藏抛物线动画工具库
  • 欢迎参加第二届中国游戏开发者大会
  • 回流、重绘及其优化
  • 写给高年级小学生看的《Bash 指南》
  • ​Spring Boot 分片上传文件
  • ​什么是bug?bug的源头在哪里?
  • #define用法
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (过滤器)Filter和(监听器)listener
  • (六)软件测试分工
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (转)scrum常见工具列表
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET CF命令行调试器MDbg入门(一)
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET的数据绑定
  • .net连接oracle数据库
  • .Net小白的大学四年,内含面经
  • /var/log/cvslog 太大
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [ Linux ] Linux信号概述 信号的产生
  • [2016.7.Test1] T1 三进制异或