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]的牛和当前循环集内最小的牛交换一次位置,帮好忙后再交换回来
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = ;
const int M = ;
int a[N] , b[N] , to[N] , vis[N] , id[M];//to[]记录置换群上的映射关系 int circle(int u)
{
int v = u , ans = ;
int cnt = ;
while(u != to[v]){
vis[v] = ;
cnt++;
ans = ans+b[v];
v = to[v];
}
ans = ans+b[v] , cnt++;
vis[v] = ;
if(cnt == ) return ;
else{
/*这里要判断一下,是不是通过利用最小编号的牛帮助这个循环集排好队是不是结果更小
最小的牛加进来帮忙就是值为b[1]的牛和当前循环集内最小的牛交换一次位置,帮好忙后
再交换回来*/
int tmp = ans + b[u] + (cnt+)*b[];
return min(tmp , ans + (cnt-)*b[u]);
}
} int main()
{
// freopen("a.in" , "r" , stdin);
int n;
while(scanf("%d" , &n) != EOF)
{
for(int i= ; i<=n ; i++)
{
scanf("%d" , a+i);
b[i] = a[i];
}
sort(b+ , b+n+);
for(int i= ; i<=n ; i++)
id[b[i]] = i;
for(int i= ; i<=n ; i++)
to[i] = id[a[i]]; //表示第i个位置被第id[a[i]]大的牛占据了
memset(vis , , sizeof(vis));
int ans = ;
for(int i= ; i<=n ; i++)
if(!vis[i]) ans += circle(i); printf("%d\n" , ans);
}
return ;
}
POJ 3270 置换群问题的更多相关文章
- poj 3270(置换群+贪心)
Cow Sorting Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6993 Accepted: 2754 Descr ...
- poj 3270(置换群)
题意:给定n头母牛的脾气大小,然后让你通过交换任意两头母牛的位置使得最后的母牛序列的脾气值从小到大,交换两头母牛的代价是两个脾气之和,使得代价最小. 分析:以前做过一道题,只有一个地方和这道题不同,但 ...
- POJ 3270 Cow Sorting(置换群)
题目链接 题意 : N头牛,每个牛的坏脾气都有一个值,每个值都不相同,把这个值按照从小到大排序,如果两个值交换,那么会花掉这两个值之和的时间,让你花最少的时间将每个值从小到大排好序,求最小的总时间. ...
- POJ 3270 Cow Sorting(置换群)
题目链接 很早之前就看过这题,思路题把,确实挺难想的,黑书248页有讲解. #include <cstdio> #include <cstring> #include < ...
- Cow Sorting POJ 3270 & HDU 2838
题目网址:http://poj.org/problem?id=3270 题目大意是:一串无序的数字,要排成增序的数列,可以交换不相邻的数,每交换两个数,sum+这两个数,使得sum最小,求最小的sum ...
- poj 3270 Cow Sorting
思路:仔细读题,看到FARMER是两两交换牛的顺序进行排序的话,应该就往置换上靠拢,而这个题果然是置换的应用(有的解题报告上说是置换群,其实这只是单个置换,不用让它构成群).我们来将这些无序的牛抽象成 ...
- poj 1026(置换群)
题意:给你一个变换规则,和一个字符串,问经过k次变换后得到的字符串. 思路:开始的时候试图去找它的整个周期,谁知道周期太大了,各种RE,后来在得知此题需要用置换群来优化,第一次接触置换群学习了下! 代 ...
- poj 3270 置换
poj 置换的应用 黑书原题P248 /** 题意: 给定序列, 将其按升序排列, 每次交换的代价是两个数之和, 问代价最小是多少 思路:1.对于同一个循环节之内的,肯定是最小的与别的交换代价最小 2 ...
- poj 3270 更换使用
1.确定初始和目标状态. 明确.目标状态的排序状态. 2.得出置换群,.比如,数字是8 4 5 3 2 7,目标状态是2 3 4 5 7 8.能写为两个循环:(8 2 7)(4 3 5). 3.观察当 ...
随机推荐
- VBScript+SCR+NetApi+Accoreconsole 批处理dwg文件
继上次powershell运行accoreconsole(https://www.cnblogs.com/NanShengBlogs/p/10981687.html)的研究之后又觉得不是很合适,毕竟p ...
- mac 修改用户权限
想安装thinkPHP 下载完以后 访问报403错误 于是百度找 也没找到原因 自己猜测是不是用户权限问题 就是下面目录为tp的用户权限 不是root 其他是root的都能访问 于是百度搜了权限如何修 ...
- redis简介及常见问题
目录 简介 特点 优点 高性能 高并发 为什么要用 redis 而不用 map/guava 做缓存? redis 和 memcached 的区别 Redis快的原因 为什么redis是单线程 为什么r ...
- linux Java环境变了配置
1. sudo /etc/profile 2.安装截图配置 输入javac 进行验证
- 关于Android皮肤更换分享
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264902&highlight=%E6%8D%A2%E8%82%A4&a ...
- [APIO2007]动物园
题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围栏里有一种动物. 你是动物园的公共主管.你要做的是,让每个来动物园的人都尽可能高兴.今天有一群小朋 ...
- 使用mysqldump导出数据库(表)
mysqldump用来备份数据库或在不同数据库之间迁移数据,mydqldump的备份内容包括用来创建表和装载表的SQL语句. 一.mysqldump使用方法 (1).备份单个数据库或数据库中的部分表, ...
- 13 继续C#中的方法,带返回值的方法介绍
在这一个练习中,我们要使用带返回值的方法.如果一个方法带返回值,那么它的形式是这样的. 定义一个带返回值的C#方法 static 返回类型 方法名字 (参数类型 参数1的名字,参数类型 参数2的名字) ...
- Linux学习日记之Deepin下查看crontab运行日志
Deepin使用 journalctl 替代了 syslog 来处理系统日志 故查看crontab运行日志应使用 journalctl -f /usr/sbin/cron
- Linux 学习(三)
Linux进程 1.进程 进程:可执行应用程序执行后产生的对应的进程,重量级:进程是由一个线程或多个线程构成: 线程:是计算机中的最小单位,轻量级(依赖和物理性是独立存在的).损耗较低 假设进程1是由 ...