poj3270--Cow Sorting(置换群)
2015-07-24 21:43
507 查看
题目链接:点击打开链接
题目大意:给出你n个数,要求把这n个数排列成有序的(由小到大),每次可以交换两个数,花费是这两个数的和,现在求最小的花费
置换群的入门
求出每一个轮换的圈,对于每一个轮换中,只有在自身内交换就能完成有序,而不需要和其它轮换交叉。
一个轮换的最小值temp,轮换中有num个数,轮换的总和是sum,整个序列的最小值min1
让一个轮换花费最少有两种可能
1、轮换自身交换,轮换的最小值和其他值交换num-1次,那么花费是sum-temp+(num-1)*temp
2、用全局的最小值和轮换的最小值交换,然后执行轮换自身交换,然后再用全局最小值把轮换的最小值交换回来
sum-temp+(num-1)*min1+2*(min1+temp)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
#define INF 0x3f3f3f3f
LL a[10010] , b[10010] , id[100010] ;
int vis[10010] ;
int main() {
int n , i , j ;
LL ans = 0 , min1 , num , sum , temp ;
memset(vis,0,sizeof(vis)) ;
scanf("%d", &n) ;
for(i = 1 , min1 = INF ; i <= n ; i++) {
scanf("%d", &a[i]) ;
b[i] = a[i] ;
id[ a[i] ] = i ;
min1 = min(min1,a[i]) ;
}
sort(b+1,b+n+1) ;
for(i = 1 ; i <= n ; i++) {
if( vis[i] || a[i] == b[i] ) continue ;
j = i ;
sum = num = 0 ;
temp = INF ;
while( !vis[ id[ b[j] ] ] ) {
j = id[ b[j] ] ;
sum += a[j] ;
num++ ;
vis[ j ] = 1 ;
temp = min(temp,a[j]) ;
}
ans += min( sum-temp+(num-1)*temp , sum-temp+(num-1)*min1+2*(min1+temp) ) ;
}
printf("%I64d\n", ans) ;
return 0 ;
}
题目大意:给出你n个数,要求把这n个数排列成有序的(由小到大),每次可以交换两个数,花费是这两个数的和,现在求最小的花费
置换群的入门
求出每一个轮换的圈,对于每一个轮换中,只有在自身内交换就能完成有序,而不需要和其它轮换交叉。
一个轮换的最小值temp,轮换中有num个数,轮换的总和是sum,整个序列的最小值min1
让一个轮换花费最少有两种可能
1、轮换自身交换,轮换的最小值和其他值交换num-1次,那么花费是sum-temp+(num-1)*temp
2、用全局的最小值和轮换的最小值交换,然后执行轮换自身交换,然后再用全局最小值把轮换的最小值交换回来
sum-temp+(num-1)*min1+2*(min1+temp)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
#define INF 0x3f3f3f3f
LL a[10010] , b[10010] , id[100010] ;
int vis[10010] ;
int main() {
int n , i , j ;
LL ans = 0 , min1 , num , sum , temp ;
memset(vis,0,sizeof(vis)) ;
scanf("%d", &n) ;
for(i = 1 , min1 = INF ; i <= n ; i++) {
scanf("%d", &a[i]) ;
b[i] = a[i] ;
id[ a[i] ] = i ;
min1 = min(min1,a[i]) ;
}
sort(b+1,b+n+1) ;
for(i = 1 ; i <= n ; i++) {
if( vis[i] || a[i] == b[i] ) continue ;
j = i ;
sum = num = 0 ;
temp = INF ;
while( !vis[ id[ b[j] ] ] ) {
j = id[ b[j] ] ;
sum += a[j] ;
num++ ;
vis[ j ] = 1 ;
temp = min(temp,a[j]) ;
}
ans += min( sum-temp+(num-1)*temp , sum-temp+(num-1)*min1+2*(min1+temp) ) ;
}
printf("%I64d\n", ans) ;
return 0 ;
}
相关文章推荐
- js函数在frame中的相互调用详解
- Ognl表达式 值栈对象ValueStack
- PHP 一个可以过滤非法脚本的函数
- 队列训练
- C语言中内联函数的作用 inline
- C++出现Expression : invalid opedrator < 的解决方法
- 疯狂java讲义中的习题,设计一个简单的计算器。
- dd if=/dev/zero of=的含义是什么?Linux 下的dd命令使用详解
- poj 1702 平衡三进制
- dd sKip 和 seek参数理解
- HD 2005 第几天?
- Humble Numbers
- mark
- Clear All of Them I(HDU 3920状压dp)
- hdu 1864 最大报销额 dp
- org.springframework.web.util.NestedServletException:
- Matlab 高斯分布 均匀分布 以及其他分布 的随机数
- LeetCode Binary Tree Preorder Traversal 先根遍历
- 7_24_heml_美食网设计_3_完整稿
- [LeetCode]Reverse Words in a String