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.观察当 ...
随机推荐
- bzoj 1774: [Usaco2009 Dec]Toll 过路费【排序+Floyd】
非常迷的一道题啊 我觉得挺对的版本只得了30 总之就是Floyd·改,开两个数组,一个是d[i][j]就是普通的只有边权的最短路,a[i][j]是题目要求的那种 具体改的地方是把枚举中转点的地方把中转 ...
- P3482 [POI2009]SLO-Elephants
传送门 首先,交换关系肯定是构成一个环的时候最优 如果这个环是自环,不用交换了 如果环的大小为2,直接交换便是 否则的话,我们可以用环里最小的点最为交换媒介,然后去和其他交换直到到达正确的位置,那么环 ...
- QQ自动登录Demo源码(附全套WindowsApi)
在开发过程中,偶尔会有自动化操作软件的需求,便想到用句柄实现自动化的功能,记录下知识点,以作备忘. 实现流程: 获取窗口句柄,根据定位获取input,调用windowsapi模拟鼠标点击, 输入 , ...
- php可以定义数组的常量吗
是这样吗?<?php define('BEST_PHPER',array('name'=>'巩文','address'=>'china')); My God,明确告诉你不可以:原因是 ...
- SeasLog的日志
https://github.com/Neeke/SeasLog/blob/master/README_zh.md 中文文档地址, 这是一个很好用的记录日志扩展,可以用于项目之中
- [Qt Quick入门] 基本元素初体验
Qt Quick作为QML语言的标准库,提供了很多基本元素和控件来帮助我们构建Qt Quick应用.这节我们简要地介绍一些Qt Quick元素,如Rectangle.Item.Text.Button. ...
- [BZOJ:3162]:独钓寒江雪
题解: 求本质不同的独立集的个数 首先独立集的个数是很好做的 \(f[u][0/1]\)表示节点\(u\)不选/选的方案数 然后dp就是 \(f[u][0] = f[u][0] * (f[v][0] ...
- DFS HDU 5305 Friends
题目传送门 /* 题意:每个点都要有偶数条边,且边染色成相同的两部分,问能有多少种染色方法 DFS+剪枝:按照边数来DFS,每种染色数为该点入度的一半,还有如果点不是偶数边就不DFS 这是别人的DFS ...
- 236 Lowest Common Ancestor of a Binary Tree 二叉树的最近公共祖先
给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先. 详见:https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tre ...
- mysqldump使用笔记
mysqldump备份简述 mysqldump可产生两种类型的输出文件,取决于是否选用 --tab=dir_name选项. 1.不使用 --tab=dir_name选项,mysqldump产生的数据文 ...