关于网易内推编程题堆棋子的解法

第一题堆棋子,当场对角懵逼、拉格朗日懵逼、。。。然后就自然而然地跪了= =。心态很重要,心态炸了一切都完了。
后来跟室友讨论了一下,算是完整的找到了一个解法,然后上来翻帖子发现精品贴已经贴出来了,思路完全一样,但是缺少说明和证明,所以在这里补充一下。
首先得证明这么一个问题,当给定i个棋子的坐标后,最后全部汇聚到一个格子,使总移动步数最少,则这个格子的横坐标应该是所有i个棋子的横坐标的中位数,纵坐标应该是所有i个棋子的纵坐标的中位数(但是要注意该点不一定是i个点之一,这个比较容易被忽略)。室友提出来的,当时我就震惊了,膜拜一下室友。具体证明起来我表达能力较差,直接拋一个博客链接好了:http://blog.csdn.net/zhang20072844/article/details/13372753
曼哈顿距离有意思的地方就在于求和的时候可以把x和y解耦,然后分别考虑。退化到一维后,把上面链接中带权中位数的各权值设为1即可。文中给出的证明我没看(太长不看。。。),其实一维的问题画图很容易证明,给个思路:考虑第一个数和最后一个数的距离、第二个数和倒数第二个数的距离、...。
好了,上面的问题解决后,剩下的就相对简单了。不过有的人可能会想,既然给定i个点后汇聚点的坐标求法知道了,但是一共有n个点啊,选出i个点出来也相当麻烦呢,这里给出的回答是不用选。由于不管i取何值,以及怎么选出这i个点,最后的汇聚点的横坐标一定是n个点的横坐标之一,纵坐标一定是n个点的纵坐标之一,所以只需考虑这n*n种情况就可以了。这其实帮助我们把搜索目标从n个点的矩形包络的量级缩减到了n*n的量级。
最后,设一个有n*n行,n列的矩阵res,每一行存储n*n种汇聚点之一到n个点的曼哈顿距离,然后对每一行从小到大排序,然后逐行依次把第i列赋值为前i-1列数值之和。这时候的矩阵所存储的,其实是对于每一种汇聚点(对应每一行),把离其最近的i个点汇聚过来所需要的总步数。所以,最后的最后,对矩阵逐列求最小值,即为答案。
下面贴出C++的代码,变量命名一塌糊涂,见谅。。。(有一个优化策略,就是n个点的所有横坐标(以及纵坐标,道理一样)中,可能有重复值,这时只用选取一次即可,类似于求一个unique,但是对STL不太熟,就没做= =)
#include <iostream>
#include <algorithm>
using namespace std;

int main(){
    int n;
    cin>>n;
    int x[n];
    int y[n];
    for(int i=0;i<n;i++)
        cin>>x[i];
    for(int i=0;i<n;i++)
        cin>>y[i];
    int res[n*n][n];
    //计算n个点到n*n个候选目标点的距离
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++){
                res[i*n+j][k] = abs(x[i]-x[k])+abs(y[j]-y[k]);
            }
    //对每个候选目标点到输入的n个点的距离排序(即对res的每一行排序)
    for(int i=0;i<n*n;i++)
        sort(*res+i*n,*res+(i+1)*n);
    //res的第i列,赋值为前i-1列之和,即距其最近的i个点移到该目标点的总移动次数
    for(int i=0;i<n;i++){
        if(i==0)
            continue;
        for(int j=0;j<n*n;j++){
            res[j][i]+=res[j][i-1];
        }
    }
    //求res每一列的最小值,即为答案
    for(int i=0;i<n;i++)
        for(int j=0;j<n*n-1;j++)
            res[0][i] = min(res[0][i],res[j+1][i]);
    for(int i=0;i<n;i++)
        i==0?cout<<res[0][i]:cout<<' '<<res[0][i];
    return 0;
}

#网易##算法工程师#
全部评论
赞一个
点赞 回复 分享
发布于 2017-08-13 14:34
棒棒!
点赞 回复 分享
发布于 2017-08-13 14:37
很明白!赞
点赞 回复 分享
发布于 2017-08-13 14:53
有个地方不明白,就是给出的博客链接上一下说n是奇数的时候取最中间两个值的平均数,一下又说取n/(2+1)
点赞 回复 分享
发布于 2017-08-13 15:33
厉害了,总是以为接近了答案  总是不对 现在终于明白了
点赞 回复 分享
发布于 2017-08-13 16:08
给赞  终于做出来了。
点赞 回复 分享
发布于 2017-08-13 16:54
点赞 回复 分享
发布于 2017-08-13 23:49
6666666666
点赞 回复 分享
发布于 2017-08-13 23:53

相关推荐

最近又搬回宿舍了,在工位坐不住,写一写秋招起伏不断的心态变化,也算对自己心态的一些思考表演式学习从开始为实习准备的时候就特别焦虑,楼主一开始选择的是cpp后端,但是24届这个方向已经炸了,同时自己又因为本科非92且非科班,所以感到机会更加迷茫。在某天晚上用java写出hello&nbsp;world并失眠一整晚后选择老本行干嵌入式。理想是美好的,现实情况是每天忙但又没有实质性进展,总是在配环境,调工具,顺带还要推科研。而这时候才发现自己一直在表演式学习,徘徊在设想如何展开工作的循环里,导致没有实质性进展。现在看来当时如果把精力专注在动手写而不是两只手端着看教程,基本功或许不会那么差。实习的焦虑5月,楼主...
耶比:哲学上有一个问题,玛丽的房间:玛丽知道眼睛识别色彩的原理知道各种颜色,但是她生活在黑白的房间里,直到有一天玛丽的房门打开了她亲眼看到了颜色,才知道什么是色彩。我现在最大可能的减少对非工作事情的思考,如果有一件事困扰了我, 能解决的我就直接做(去哪里或者和谁吵架等等……),解决不了的我就不想了,每一天都是最年轻的一天,珍惜今天吧
投递比亚迪等公司10个岗位 > 秋招被确诊为…… 牛客创作赏金赛
点赞 评论 收藏
分享
评论
点赞
收藏
分享
正在热议
# 25届秋招总结 #
439972次浏览 4484人参与
# 春招别灰心,我们一人来一句鼓励 #
41352次浏览 523人参与
# 阿里云管培生offer #
119621次浏览 2219人参与
# 地方国企笔面经互助 #
7914次浏览 18人参与
# 虾皮求职进展汇总 #
113497次浏览 880人参与
# 实习,投递多份简历没人回复怎么办 #
2453683次浏览 34846人参与
# 北方华创开奖 #
107229次浏览 598人参与
# 实习必须要去大厂吗? #
55552次浏览 959人参与
# 同bg的你秋招战况如何? #
75178次浏览 548人参与
# 提前批简历挂麻了怎么办 #
149763次浏览 1976人参与
# 投递实习岗位前的准备 #
1195578次浏览 18546人参与
# 你投递的公司有几家约面了? #
33165次浏览 188人参与
# 双非本科求职如何逆袭 #
661770次浏览 7394人参与
# 机械人春招想让哪家公司来捞你? #
157585次浏览 2267人参与
# 如果公司给你放一天假,你会怎么度过? #
4714次浏览 53人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11214次浏览 253人参与
# 发工资后,你做的第一件事是什么 #
12359次浏览 61人参与
# 工作中,努力重要还是选择重要? #
35521次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20068次浏览 240人参与
# 实习想申请秋招offer,能不能argue薪资 #
39205次浏览 314人参与
# 我的上岸简历长这样 #
451863次浏览 8087人参与
# 非技术岗是怎么找实习的 #
155831次浏览 2120人参与
牛客网
牛客企业服务