zoukankan      html  css  js  c++  java
  • 【CodeVS 2845】排序的代价

    http://codevs.cn/problem/2845/
    好难的题啊qwq
    没想到把排好序的数组的第i位和原数组的第i位的值看成一个单射函数,这样这是一个长度为n的置换。
    对于置换的其中一个循环,如果长度为1就不用管了,否则循环中每个数至少要交换一次。
    这样我们让循环中不是最小的元素只交换一次,循环中最小的元素交换很多次(具体地,循环节长度-1次)就可以做到这个循环的代价最小。
    当然这个循环的代价还可能更小,那就是让循环中的最小元素跟整个数列中的最小元素换一下,先让数列中的最小元素代替循环中的最小元素进行交换,最后再换回来就可以了。
    重点是贪心思想。

    #include<cstdio>
    #include<bitset>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 1003;
    
    bitset <N> vis;
    int n, a[N], H[N], cnt, mn, ret, ans, id[N], tot, casenum = 0;
    
    int main() {
    	while (~scanf("%d", &n)) {
    		cnt = ans = 0;
    		vis.reset();
    		for (int i = 1; i <= n; ++i) scanf("%d", a + i), H[++cnt] = a[i];
    		stable_sort(H + 1, H + cnt + 1); mn = H[1];
    		++cnt;
    		for (int i = 1; i <= n; ++i) a[i] = lower_bound(H + 1, H + cnt, a[i]) - H;
    		
    		for (int i = 1; i <= n; ++i)
    			if (!vis[i]) {
    				vis[id[tot = 1] = i] = 1;
    				int tmp = a[i];
    				while (!vis[tmp]) {
    					vis[tmp] = 1;
    					id[++tot] = tmp;
    					tmp = a[tmp];
    				}
    				
    				tmp = 1;
    				for (int i = 2; i <= tot; ++i)
    					if (id[i] < id[tmp]) tmp = i;
    				ret = 0;
    				for (int i = 1; i <= tot; ++i)
    					if (i != tmp) ret += H[id[i]];
    				ret += min(H[id[tmp]] * (tot - 1), ((H[id[tmp]] + mn) << 1) + mn * (tot - 1));
    				ans += ret;
    			}
    		
    		if (ans == 0) break;
    		printf("Case %d: %d
    ", ++casenum, ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    mybatis mybatis-generator 代码自动生成工具使用
    spring初步
    spring基于xml和注解配置事务
    强软弱虚四大引用
    线程通信的几种实现方式
    java8新特性之方法引用和构造器引用
    JAVA四大内置函数
    JAVA四大内置函数
    JSR303的使用
    设计模式之建造者模式
  • 原文地址:https://www.cnblogs.com/abclzr/p/6429753.html
Copyright © 2011-2022 走看看