zoukankan      html  css  js  c++  java
  • 分治

      将一个规模为n的问题分解为k个规模较小的相同子问题,这些子问题相互独立且与原问题相同。递归地这些子问题,然后将子问题地解合并得到原问题的解。

    合并排序是利用分治策略实现对n格元素进行排序的算法。

    eg:

    Description

    N soldiers of the land Gridland are randomly scattered around the country. 
    A position in Gridland is given by a pair (x,y) of integer coordinates. Soldiers can move - in one move, one soldier can go one unit up, down, left or right (hence, he can change either his x or his y coordinate by 1 or -1). 

    The soldiers want to get into a horizontal line next to each other (so that their final positions are (x,y), (x+1,y), ..., (x+N-1,y), for some x and y). Integers x and y, as well as the final order of soldiers along the horizontal line is arbitrary. 

    The goal is to minimise the total number of moves of all the soldiers that takes them into such configuration. 

    Two or more soldiers must never occupy the same position at the same time. 

    Input

    The first line of the input contains the integer N, 1 <= N <= 10000, the number of soldiers. 
    The following N lines of the input contain initial positions of the soldiers : for each i, 1 <= i <= N, the (i+1)st line of the input file contains a pair of integers x[i] and y[i] separated by a single blank character, representing the coordinates of the ith soldier, -10000 <= x[i],y[i] <= 10000. 

    Output

    The first and the only line of the output should contain the minimum total number of moves that takes the soldiers into a horizontal line next to each other.

    Sample Input

    5

    1 2

    2 2

    1 3

    3 -2

    3 3

    Sample Output

    8

    通过适当的移动顺序和移动路线可以使得同一时刻不会有两名士兵站在同一点。

    题目要求移动的最少步数

    题目要求可转化为求士兵站立的“最终位置”,即如何取“最终位置”使得士兵移动的步数最少
    1. Y轴方向上的考虑
        设目标坐标为Y0,即n个士兵最终需要移动到的Y轴的坐标值为M
      n个士兵的Y轴坐标分别为:
         Y1,Y2 …… …… Yn
    移动步数

    S=|Y1-Y0|+|Y2-Y0|+ …… …… +|Yn-Y0|
    结论:Y0取所有Yi的中间值时可以使得S达到最小。

    (可以证明)

    解决办法:

    1.对所有的Y轴坐标进行排序(O(nlogn))或者进行线性时间选择(O(n))然后取“中间”点的Y轴坐标值作为最佳位置Y0的值
        2.通过公式求出Y轴方向上移动的最优步数


    2. X轴方向上的考虑
      (1)首先需要对所有士兵的X轴坐标值进行排序
      (2)然后,按从左至右的顺序依次移动到每个士兵所对应的“最终位置”(最优),所移动的步数总和就是X轴方向上需要移动的步数
      设排序后n个士兵在X轴坐标为:

    X1’,X2’ …… …… Xn’

    他们最终位置”的X轴坐标值为:

    k,k+1,k+2 …… …… k+(n-1)
    则所求移动的步数
        S=|X1’-k| + |X2’-(k+1)|+ …… +|Xn’-(k+(n-1)|
    经过变形

    S=|X1’-k|+ |(X2’-1)-k|+ …… +|(Xn’-(n-1))-k|
    注意到公式的形式与Y轴方向上的考虑一样,同样是n个已知数分别减去一个待定数后取绝对值,然后求和

    问题转化为:

    求出x1’, x2’-1,… Xn’-(n-1)的中位数,即求得k值,最后算出最优解。

     

    #include<stdio.h> 
    #include<math.h> 
    /*========寻找中位数==========*/
    int RandSelect(int *a,int p,int n){
    	Q_sort(a,p,n);
    	if(n%2==1) return a[(n+1)/2];
    	else return (a[n/2]+a[(n/2)+1])/2;
    }
    /*========排序======*/
    int Q_sort(int *a,int low,int high){
    	int i,j,min,flag,temp;
    	for(i=low;i<=high;i++){
    		min=a[i];
    		flag=i;
    		for(j=i;j<=high;j++){
    			if(a[j]<min) {
    				min=a[j];
    				flag=j;
    			}
    		}
    		if(flag!=i){
    			temp=a[flag];
    			a[flag]=a[i];
    			a[i]=temp;
    		}
    	}
    	
    }
    int main()
    {
    	int x[10001],y[10001],x1[10001],n,a,sum,xkey,ykey;
    	scanf("%d",&n);    //获取士兵数目
    	sum=0;
    	for(a=1;a<=n;a++){
    	scanf("%d %d",&x[a],&y[a]); 
    	}                //接收士兵位置
    	Q_sort(x,1,n);
    	for(a=1;a<=n;a++) x1[a]=x[a]-(a-1);
    	ykey=RandSelect(y,1,n);
            xkey=RandSelect(x1,1,n);
    	for(a=1;a<=n;a++){
    		sum+=abs(y[a]-ykey);
    		sum+=abs(x1[a]-xkey);
    	}
    	printf("%d",sum);
    	return 0; 
    }
    

      

    你一定会喜欢那个因为喜欢她而发光的自己!
    个人博客:http://www.yanghelong.top
  • 相关阅读:
    反转字符串
    数组
    复杂度分析(二)
    复杂度分析(一)
    业务应该这么写--特性
    5种方法快速启动一个应用程序
    业务应该这么写--表达式树
    业务应该这么写--泛型
    业务应该这么写--异常处理
    关于关系型数据库外键,要减轻数据库压力的一些说法
  • 原文地址:https://www.cnblogs.com/zzu-general/p/8466889.html
Copyright © 2011-2022 走看看