示例1 输入
4 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]; }