分治法 - 士兵排隊問題


來自PTA的一道習題:

在一個划分成網格的操場上,n個士兵散亂地站在網格點上。網格點用整數坐標(x,y)表示。士兵們可以沿網格邊往上、下、左、右移動一步,但在同一時刻任一網格點上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成一個水平隊列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何選擇x和y的值才能使士兵們以最少的總移動步數排成一行。

編程計算使所有士兵排成一行需要的最少移動步數。

輸入格式:
第1行是士兵數n,1≤n≤10000。接下來n行是士兵的初始位置,每行有2個整數x和y,-10000≤x,y≤10000。

輸出格式:
一個數據,即士兵排成一行需要的最少移動步數。

輸入樣例:

5
1  2
2  2
1  3
3  -2
3  3

輸出樣例:

8

思路:

X軸和Y軸可以分開考慮。

士兵y軸坐標不變,可以假想為有一條垂直於y軸的直線,所有士兵都要移動到這條直線上,顯然這是一個求中位數Y的問題。解決方法為將士兵y軸坐標排序,求得中位數后求各士兵y軸坐標據其的距離abs(y[i] - Y)
(排序不需要寫了吧,我這里用的是快排

至此,在我們的假設中所有士兵已經移動到了同一水平線上,那么x軸的呢……有了y軸的思路,x軸應該也比較容易想到,它仍是一個求中位數的問題。
我們先對士兵x軸坐標進行排序,假設排序完他們坐標x0,x1,x2……x(n - 1),而最終坐標為x,x+1,x+2……x+(n - 1),那么移動步數也就是(x0 - x) + (x1 - x -1) + …… + (x(n - 1) - x - n)= (x0 - x) + ((x1 - 1) - x) + ((x2 - 2) - x) + …… + ((x(n - 1) - (n - 1) - x) 現在它已經轉化為了求 x0,x1 - 1,x2 - 2……x(n - 1) - (n - 1)的中位數

OK!上代碼!

#include <stdio.h>
#include <math.h>

int x[10000], y[10000], s[10000];
	
void quickSort(int l, int r, int *data) 
{
    if(l >= r) return;
    int m = data[(l + r) / 2];//中間的那個
    int i = l;
    int j = r;
    while(i <= j)
	{
        while(data[i] < m)
            i++;
        while(data[j] > m)
            j--;
        if(i <= j)
		{//交換
            int tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
            i++;
            j--;
        }
    }//循環結束表示一趟已執行完
    if(l < j)
        quickSort(l, j, data);
    if(r > i)
        quickSort(i, r, data);
}

int main()
{
	int n, X, Y;
	int res = 0;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &x[i]);
		scanf("%d", &y[i]);
	}
	
	//Y軸方向上的考慮 
	quickSort(0, n - 1, y);
	
	if(n % 2)
		Y = y[(n - 1) / 2];
	else Y = (y[n / 2] + y[n / 2 - 1]) / 2;
	
    for(int i = 0; i < n; i++)
    {
        res += abs(y[i] - Y);
    }
    
    //X軸方向上的考慮
    quickSort(0, n - 1, x);
    
	for (int i = 0; i < n; i++)
	{
		s[i] = x[i] - i;
	}
	
	quickSort(0, n - 1, s);
	
	if(n % 2)
		X = s[(n - 1) / 2];
	else X = (s[n / 2] + s[n / 2 - 1]) / 2;
	
    for(int i = 0; i < n; i++)
    {
        res += abs(s[i] - X);
    }
	
    printf("%d", res);
    
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM