zoukankan      html  css  js  c++  java
  • POJ 3270

    黑书上的经典题了。我说说解这个题的巧妙的地方吧。

    首先,竟然和置换联系起来了。因为其实一个交换即至少可以使其中一个元素到达指定位置了。和循环置换联合起来,使得一个循环内的数可以一步到达指定位置,很巧妙啊。这样,用循环内的最小的数和其它数交换,需要K-1次的交换即可。另外,也可以把整个数列的最小数 i 和循环内的最小数交换,用 i 来和循环内的其他数交换的权值。 两者权值取最小的即可。

    实在巧妙。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define LL __int64
    #define N 10000
    #define inf (1<<30)
    using namespace std;
    
    int num[N+1];
    bool vis[N+1];
    struct Value{
    	int val,pos;
    }cow[N+1];
    
    bool cmp(Value a,Value b){
    	if(a.val<b.val) return true;
    	return false;
    }
    
    LL minL(LL a,LL b){
    	if(a<b) return a;
    	return b;
    }
    
    
    int main(){
    	int n,res_min,cnt,mi; LL ans,res;
    	while(scanf("%d",&n)!=EOF){
    		res_min=inf;
    		for(int i=1;i<=n;i++){
    			scanf("%d",&cow[i].val);
    			cow[i].pos=i;
    			res_min=min(res_min,cow[i].val);
    		}
    		sort(cow+1,cow+n+1,cmp);
    		for(int i=1;i<=n;i++){
    			num[cow[i].pos]=i;
    		}
    		memset(vis,false,sizeof(vis));
    		ans=0;
    		for(int i=1;i<=n;i++){
    			if(!vis[i]){
    				int k=i; cnt=0; mi=inf; res=0;
    				while(!vis[k]){
    					cnt++;
    					mi=min(mi,cow[k].val);
    					res=res+(LL)cow[k].val;
    					vis[k]=true;
    					k=num[k];
    				}
    				ans=ans+res+minL((LL)(cnt-2)*(LL)mi,(LL)mi+(LL)(cnt+1)*(LL)res_min);
    			}
    		}
    		printf("%I64d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    poj 1113 Wall 凸包的应用
    NYOJ 78 圈水池 (入门级凸包)
    Monotone Chain Convex Hull(单调链凸包)
    poj Sudoku(数独) DFS
    poj 3009 Curling 2.0(dfs)
    poj 3083 Children of the Candy Corn
    Python join()方法
    通过FISH和下一代测序检测肺腺癌ALK基因融合比较
    华大病原微生物检测
    NGS检测ALK融合大起底--转载
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4028915.html
Copyright © 2011-2022 走看看