小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.
输入包括三行,第一行一个整数n(1 ≤ n ≤ 50),表示棋子的个数 第二行为n个棋子的横坐标x[i](1 ≤ x[i] ≤ 10^9) 第三行为n个棋子的纵坐标y[i](1 ≤ y[i] ≤ 10^9)
输出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.*;
public class Main{
/*
之前尝试用dfs求出各种组合,再取中位数为所有棋子移动到的点,结果只通过70%测试用例,然后超时。。。
曼哈顿距离
思路:n个棋子,全部移动到某一点时所需的操作数最少。该点横坐标为n个棋子中横坐标之一,纵坐标为n个棋子纵坐标之一
三维数组 dist[i][j][k] 含义:对于坐标为(x[i],y[j])的点来说,它离第k个棋子a[k]的曼哈顿距离
三维数组的dist[i][j]所对应的棋盘上的点的横纵坐标由n个棋子的横纵坐标组合而成,因此有 n * n 种组合情况
求得了dist[i][j][k]之后,对dist[i][j]按从小到到大排序,即按该点离各个棋子的近远排序
当要求m个棋子位于一个坐标时,只需比较每个点上聚集m个棋子所需的最小操作数(即对于上一步排序好的dist[i][j],每一行取前m列求和),取最小即可
*/
private static int[] min;
public static void main(String[] args){
try(Scanner in = new Scanner(System.in)){
int n = in.nextInt();
int[] x = new int[n],y = new int[n];
min = new int[n];
for(int i = 0;i < n;i++){
x[i] = in.nextInt();
}
for(int i = 0;i < n;i++){
y[i] = in.nextInt();
}
int[][][] dist = getDist(x,y,n);
int count = 1;
while(count <= n){
helper(dist,count,n);
count++;
}
for(int i = 0;i < min.length - 1;i++){
System.out.print(min[i] + " ");
}
System.out.println(min[min.length - 1]);
}
}
public static int[][][] getDist(int[] x,int[] y,int n){
int[][][] dist = new int[n][n][n];
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
for(int k = 0;k < n;k++){
dist[i][j][k] = Math.abs(x[k] - x[i]) + Math.abs(y[k] - y[j]);
}
}
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
Arrays.sort(dist[i][j]);
}
}
return dist;
}
public static void helper(int[][][] dist,int count,int n){
int[] res = new int[n];
int m = Integer.MAX_VALUE;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
int sum = 0;
for(int k = 0;k < count;k++){
sum += dist[i][j][k];
}
m = Math.min(m,sum);
}
}
min[count - 1] = m;
}
}
/**
照抄别人的算法。用了好久好久。。。终于理解了。。
**/
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static int dist(int a,int b,int c,int d) {
return Math.abs(a-c)+Math.abs(b-d);
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] x = new int[n];
int[] y = new int[n];
int[] ans = new int[n];
int[] dis = new int[n];
for(int i=0;i<n;i++)
ans[i] = Integer.MAX_VALUE;
for(int i=0;i<n;i++)
x[i] = in.nextInt();
for(int i=0;i<n;i++)
y[i] = in.nextInt();
for(int i=0;i<n;i++) { //i,j,假设所需1,2...n个子都放在想[i],y[j]上
for(int j=0;j<n;j++) {
int temp = 0;
for(int k=0;k<n;k++) {
dis[k] = dist(x[k],y[k],x[i],y[j]);
}
Arrays.sort(dis);//dis中存储任意元素x[k],y[k]与格子x[i],y[j]之间的距离。
for(int k=0;k<n;k++) {
temp+=dis[k];
ans[k] = Math.min(temp, ans[k]);
}
}
}
System.out.print(ans[0]);
for(int i=1;i<n;i++)
System.out.print(" "+ans[i]);
}
}
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int n = scanner.nextInt();
int[] x = new int[n];
int[] y = new int[n];
int[] answer = new int[n];
Arrays.fill(answer, Integer.MAX_VALUE);
for(int i = 0; i < n; i++){
x[i] = scanner.nextInt();
}
for(int i = 0; i < n; i++){
y[i] = scanner.nextInt();
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
int[] array= new int[n];
for(int k = 0; k < n; k++){
array[k] = Math.abs(x[i] - x[k]) + Math.abs(y[j] - y[k]);
}
Arrays.sort(array);
int temp = 0;
for(int k = 0; k < n; k++){
temp += array[k];
answer[k] = Math.min(answer[k], temp);
}
}
}
for(int i = 0; i < n-1; i++){
System.out.print(answer[i] + " ");
}
System.out.println(answer[n-1]);
}
scanner.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = in.nextInt();
int[] x = new int[n];
int[] y = new int[n];
for (int i = 0; i < n; i++) {
x[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
y[i] = in.nextInt();
}
List<List<Integer>> distances = new ArrayList<>();
countDistances(x, y, distances);
//计算至少有一个格子放i颗棋子的最小移动次数
for (int i = 1; i <= n; i++) {
int minMoved = Integer.MAX_VALUE;
//计算移动i颗棋子到一个格子的最小操作次数
for (List<Integer> disTmp : distances) {
int minMovedTmp = 0;
for (int j = 0; j < i; j++) {
minMovedTmp += disTmp.get(j);
}
minMoved = Math.min(minMoved, minMovedTmp);
}
System.out.print(minMoved);
if(i != n) {
System.out.print(" ");
}
}
}
}
/**
* 最后的结果只可能出现在棋子横纵坐标的组合上
* 比如两颗棋子的坐标为(1, 2)和(5, 6) 那最后的结果只可能出现在(1, 2),(1, 6),(5, 2),(5, 6)
* 按总共候选点的个数就是n * n
* 计算出所有棋子到每个候选点的距离,并对这个距离排序,根据计算出的距离选择最优解
* 比如要求有一个格子有3颗棋子最小移动次数,只需要计算每个候选点放三颗棋子的移动次数,然后取最小值
*
* @param x
* @param y
* @param distances
*/
private static void countDistances(int[] x, int[] y, List<List<Integer>> distances) {
for (int i = 0; i < x.length; i++) {
for (int j = 0; j < y.length; j++) {
//(i,j) 为候选点
//计算每颗棋子到候选点的距离,任意一颗棋子到(i,j)的移动次数为坐标相减取绝对值相加
List<Integer> disTmp = new ArrayList<>();
for (int k = 0; k < x.length; k++) {
disTmp.add(Math.abs(x[k] - x[i]) + Math.abs(y[k] - y[j]));
}
//对计算出的距离排序
Collections.sort(disTmp);
distances.add(disTmp);
}
}
}
}
/*/*使用暴力枚举的方法,千万不要只考虑出现的n个点的位置,我之前就是只考虑这个,写的很简单,结果只AC 50%应该要考虑这n个点附近的点,这里的解法就是考虑了所有点的横坐标上出现过纵坐标的点,也就是横坐标不同数字个数*纵坐标不同的数字个数。这里的算法重复计算了相同的点,如果采用两个set集合,时间复杂度会好一点*/import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner scan = new Scanner(System.in); int n = scan.nextInt(); int[]X = new int[n]; int[]Y = new int[n]; for(int i=0;i<n;i++){ X[i] = scan.nextInt(); } for(int i=0;i<n;i++){ Y[i] = scan.nextInt(); } int[] res = new int[n]; for(int i=0;i<n;i++){ res[i] = Integer.MAX_VALUE; } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ for(int k=0;k<n;k++){ int[] res2 = new int[n]; for(int l=0;l<n;l++){ res2[l] = Math.abs(X[l]-X[j])+Math.abs(Y[l]-Y[k]); } Arrays.sort(res2); int res3 = 0; for(int l=0;l<=i;l++){ res3 = res3 + res2[l]; } res[i] = Math.min(res3, res[i]); } } } for(int i=0;i<n;i++){ if(i<n-1){ System.out.print(res[i]+" "); }else{ System.out.print(res[i]); } } } }