网易校招编程-堆棋子

题目描述

小易将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]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值