网易笔试题-堆棋子

转自:https://blog.csdn.net/u013616945/article/details/77750698

题目


小易将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)中
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

示例1 
输入


1 2 4 9 
1 1 1 1 
输出

0 1 3 10

基本思想:

首先明确曼哈顿距离:

坐标(x1, y1)的i点与坐标(x2, y2)的j点的曼哈顿距离为: 
d(i,j)=|X1-X2|+|Y1-Y2|.

接着我们应该知道若在一维平面上,存在A,B,C三个点,那么平面上若存在一个点到3个点的曼哈顿距离之和的最小的点应该落在A,B,C其中一个点中。如下图:

这里写图片描述

上面B应该为最小的点。

最后我们应该注意到对于二维平面,我们可以将二维平面上的点(x,y)分别投影到对应的x轴和y轴,那么我们就可以依次求出x轴上最小曼哈顿距离的点和y轴上最小曼哈顿距离的点,两个点的坐标就是本题的解。

代码如下:

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector<int> minOPs(int size,vector<int> x,vector<int> y){
    vector<int> res(size);
    for(int i=0;i<size;i++){
        res[i]=INT_MAX;
    }

    priority_queue<int,vector<int>,greater<int>> pq;
    for(int i=0;i<size;i++){
        for(int j=0;j<size;j++){
            //每个点与(x[i],y[i]) 求曼哈顿距离,并存入优先队列
            //优先队列是一个小根堆 
            for(int k=0;k<size;k++){
                pq.push(abs(x[k]-x[i])+abs(y[k]-y[j]));
            }

            int resI=0;
            int sum=0;
            //依次分别取出优先队列的值,分别为每个棋子到(x[i],y[i])距离的最小值,次小值...最大值 
            while(!pq.empty()){
                sum+=pq.top();
                pq.pop();
                res[resI]=min(res[resI],sum);//更新1...size个棋子堆在一起的最小值 
                resI++;
            }
        }
    }
    return res;

}

int main(){
    int size;
    cin>>size;
    vector<int> x(size);
    vector<int> y(size);
    int tmp;
    for(int i=0;i<size;i++){
        cin>>tmp;
        x[i]=tmp;
    } 
    for(int i=0;i<size;i++){
        cin>>tmp;
        y[i]=tmp;
    }
    vector<int> res(size);
    res=minOPs(size,x,y);
    for(int i=0;i<size-1;i++){
        cout<<res[i]<<" ";
    }
    cout<<res[size-1];
} 

猜你喜欢

转载自blog.csdn.net/ljh0302/article/details/80826632