题目描述
小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.
题解
这道题其实想明白了就很简单,直接暴力求解即可。首先我们要明确一点,最终的最优点X坐标一定是某个点的X坐标,Y坐标一定是某个点的Y坐标。
关于证明,我们可以进行以下的尝试:
首先假设最优点左边的棋子个数为A,右边的棋子个数为B,如果最优点不在某一个棋子点上,如下图所示。
我们可以发现A=3,B=1,如果此时将X0点向左移,会得到更优的解(也就是左边点多,向左拉更优)此时,我们就可以得到一个结论,A!=B的时候,最优点一定在棋子点上。
如果A==B,如下图所示。
那么我们可以发现,此时无论在2、3、4号点,都是最优点,因此最优点也一定存在于棋子点上。
综上所述,最优点一定存在于棋子点上。因此我们只要暴力枚举最优点即可。
代码
#include <bits/stdc++.h>
#define LL long long
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MAXN 60
#define COUT(x) cout<<x<<endl
using namespace std;
struct Node{
int x,y;
};
int dis(int x1,int y1,int x2,int y2){
return abs((x1-x2))+abs((y1-y2));
}
Node nodes[MAXN];
int ans[MAXN];
int len[MAXN];
int main(){
MEM(nodes,0);
MEM(ans,INF);
int n;
scanf("%d",&n);
UP(i,0,n) scanf("%d",&nodes[i].x);
UP(i,0,n) scanf("%d",&nodes[i].y);
UP(i,0,n){
UP(j,0,n){
UP(k,0,n) len[k]=dis(nodes[i].x,nodes[j].y,nodes[k].x,nodes[k].y);
sort(len,len+n);
int now=0;
UP(k,0,n){
now+=len[k];
ans[k]=min(ans[k],now);
}
}
}
UP(i,0,n){
if(i!=n-1) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
}