小易將n個棋子擺放在一張無限大的棋盤上。第i個棋子放在第x[i]行y[i]列。同一個格子允許放置多個棋子。每一次操作小易可以把一個棋子拿起並將其移動到原格子的上、下、左、右的任意一個格子中。小易想知道要讓棋盤上出現有一個格子中至少有i(1 ≤ i ≤ n)個棋子所需要的最少操作次數.
input:
輸入包括三行,第一行一個整數n(1 ≤ n ≤ 50),表示棋子的個數
第二行爲n個棋子的橫座標x[i](1 ≤ x[i] ≤ 10^9)
第三行爲n個棋子的縱座標y[i](1 ≤ y[i] ≤ 10^9)
output:
輸出n個整數,第i個表示棋盤上有一個格子至少有i個棋子所需要的操作數,以空格分割。行末無空格
如樣例所示:
對於1個棋子: 不需要操作
對於2個棋子: 將前兩個棋子放在(1, 1)中
對於3個棋子: 將前三個棋子放在(2, 1)中
對於4個棋子: 將所有棋子都放在(3, 1)中
樣例輸入:
4
1 2 4 9
1 1 1 1
樣例輸出:
0 1 3 10
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
int cheeseNum=in.nextInt();
int[] x=new int[cheeseNum];
int[] y=new int[cheeseNum];
//輸入
for(int i=0;i<cheeseNum;i++)
{
x[i]=in.nextInt();
}
for(int i=0;i<cheeseNum;i++)
{
y[i]=in.nextInt();
}
int[] result=new Main().getOperaterCount(x,y,cheeseNum);
for(int i=0;i<cheeseNum-1;i++)
{
System.out.print(result[i]+" ");
}
System.out.print(result[cheeseNum-1]);
}
public int[] getOperaterCount(int[] x,int[] y,int cheeseNum)
{
int[] resArray=new int[cheeseNum];
//將所有值賦爲最大值 用於記錄棋盤中有棋子的節點到可能爲棋子彙集位置的距離
//resArray[0]表示格子中只有一個節點時需要進行操作的最少次數 爲什麼 往下看
for(int i=0;i<cheeseNum;i++)
{
resArray[i]=Integer.MAX_VALUE;
}
PriorityQueue<Integer> queue=new PriorityQueue<>();//有序隊列 省去排序過程
int index=0;//用於遍歷
int sum=0;
//聚集點的橫座標肯定是原棋子橫座標的其中一個 縱座標同理 以證明
//所以這個雙重循環用來遍歷所有可能的聚集點
for(int i=0;i<cheeseNum;i++)
{
for(int j=0;j<cheeseNum;j++)
{
//接下來這個循環 用於查找所有棋子到當前聚集點的距離
for(int k=0;k<cheeseNum;k++)
{
queue.add(Math.abs(x[k]-x[i])+Math.abs(y[k]-y[j]));
}
//隊列中記錄所有棋子到(x[i],y[j])的距離 且按照升序排序
index=0;//刷新resArray數組
sum=0;//到達聚集點的棋子數 resArray[i] i+1顆棋子到(x[i],y[j])的最短距離
while(!queue.isEmpty())
{
sum+=queue.poll();
//更新過程 格子中有i個棋子時,i不同時,聚集點也可能不同
resArray[index]=Math.min(resArray[index],sum);
index++;
}
}
}
return resArray;
}
}