网易2018校招内推编程题-堆棋子-C++实现

Posted on 2018-08-02 10:44  Apelike  阅读(515)  评论(0编辑  收藏  举报

链接:https://www.nowcoder.com/questionTerminal/27f3672f17f94a289f3de86b69f8a25b
来源:牛客网

[编程题]堆棋子
小易将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

输入

4
1 2 4 9
1 1 1 1

输出

0 1 3 10

解法

暴力枚举所有可能的点。
如图所示,黑点为输入点。所需遍历的点为红线的交点,红圈表示。
当时自己写的是遍历了外围红线所构成的封闭矩形里面所有的点了,只有60%的AC率,原因超时。
看了康学长的代码,才知道有些点不需要遍历,只需要遍历红线交点即可。
自己又重新写了一遍,给大家参考。

 

 

 


#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
void getInput(vector<int>&arr, const int &k)
{
	for (int i = 0; i < k; i++)
	{
		cin >> arr[i];
	}
}
void getDist(vector<int>&x, vector<int>&y, vector<int>&dist)
{
	int size = x.size();
	for (int i = 0; i < size; ++i)
	{
		for (int j = 0; j < size; ++j)//遍历所有组合点
		{
			vector<int> tempdist(size,0);
			for (int k = 0; k < size; ++k)
			{
				tempdist[k] = abs(x[k] - x[i]) + abs(y[k] - y[j]);
			}
			sort(tempdist.begin(),tempdist.end());//单点距离排序
			for (int m = 1; m < size; ++m)//多点距离和升序
			{
				tempdist[m] = tempdist[m - 1] + tempdist[m];
			}
			if (dist.size() == 0)
			{
				dist = tempdist;
			}
			else
			{
				for (int m = 0; m < size; ++m)//选择最小
				{
					if (tempdist[m] < dist[m])
						dist[m] =  tempdist[m];
				}
			}
		}
	}
}
int main()
{
	int n;
	vector<int> result;
	cin >> n;
	vector<int> x(n,0), y(n,0);
	getInput(x, n);
	getInput(y, n);
	getDist(x,y, result);
	for (int i = 0; i<result.size(); ++i)
	{
		cout << result[i] << " ";
	}
	cout << endl;
	return 0;
}