堆棋子

题目描述:

小易将n个棋子摆放在一张无限大的棋盘上,第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现一个格子至少有i(1<=1<=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


输出例子1:

0 1 3 10


题目分析:

对于一个格子放n个棋子所需的操作步骤,是求这些棋子到它们中心点的距离之和;对于求一个格子放n-1个棋子,则需要先从n个棋子中剔除掉一个最远的棋子,再对剩下n-1个点,求它们到中心点的距离之和,以此类推。在其中,需要生成一个最小生成树,来快速地搜索最远的棋子。



// Source.cpp  
// ------------------------------------------------------------------ -  
// Reference: 
// Authors : LSS  
// Date : 13 / 08 / 2017  
// Last modified : 13 / 08 / 2017  
// ------------------------------------------------------------------ -  


#include <iostream>    
#include <vector>      
#include <string>    
#include <algorithm>   
#include <utility>


using namespace std;

typedef struct Coords
{
	int x =-1;
	int y =-1;
};

bool DistCompare(pair<int, Coords> s1, pair<int, Coords> s2) { return s1.first < s2.first; }
bool PairIntIntCompareMin(pair<int, int> s1, pair<int, int> s2) { return s1.first < s2.first; }
bool PairIntIntCompareMax(pair<int, int> s1, pair<int, int> s2) { return s1.first > s2.first; }

int MinStep(vector<int> &X, vector<int> &Y, vector<bool> &binsel, int m)
{
	int cordx;
	int cordy;

	int sumx = 0;
	int sumy = 0;
	int sumn = 0;

	for (int i = 0; i < X.size(); i++)
	{
		if (binsel[i])
		{
			sumx += X[i];
			sumy += Y[i];
			sumn += 1;
		}
	}

	if (sumn != m)
		return -1;

	cordx = round((double)sumx / m);
	cordy = round((double)sumy / m);

	int minstep = 0;
	for (int i = 0; i < X.size(); i++)
	{
		if (binsel[i])
			minstep = minstep + abs(X[i]-cordx)+ abs(Y[i]-cordy);
	}

	return minstep;

}

int main(int argc, char** argv[])
{
	int n;
	while (cin >> n)
	{
		vector<int> X(n, 0);
		vector<int> Y(n, 0);    // the integral coordinate    
		for (int i = 0; i<n; i++)
		{
			cin >> X[i];
		}

		for (int i = 0; i < n; i++)
		{
			cin >> Y[i];
		}

		// Minimum Spanning Tree
		vector<vector<int>> G(n, vector<int>(n, INT_MAX));
		vector<pair<int, Coords>> distCoords(n*(n-1)/2, make_pair(1, Coords())); //(dist, x, y)
		int tempt = 0;
		for (int i = 0; i < n; i++)
		{
			for (int j = i+1; j < n; j++)
			{
				G[i][j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);
				G[j][i] = G[i][j];
				Coords temp;
				temp.x = i;
				temp.y = j;
				/*distCoords[tempt++] = make_pair(G[i][j], Coords{i, j});*/
				distCoords[tempt++] = make_pair(G[i][j], temp);
			}
		}

		sort(distCoords.begin(), distCoords.end(), DistCompare);

		/*for (size_t i = 0; i < distCoords.size(); i++)
		{
			cout << distCoords[i].first << ' ' << distCoords[i].second.x << ' ' << distCoords[i].second.y << endl;
		}
*/
		vector<bool> binVecs(n, false);
		vector<vector<pair<int, int>>> vecsEdges(n); // pair(int dist, vec i)

		for (size_t i = 0; i < distCoords.size(); i++)
		{
			if (!(binVecs[distCoords[i].second.x] & binVecs[distCoords[i].second.y]))
			{
				vecsEdges[distCoords[i].second.x].push_back(make_pair(distCoords[i].first, distCoords[i].second.y));
				vecsEdges[distCoords[i].second.y].push_back(make_pair(distCoords[i].first, distCoords[i].second.x));

				binVecs[distCoords[i].second.x] = true;
				binVecs[distCoords[i].second.y] = true;
			}
		}

	/*	for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < vecsEdges[i].size(); j++)
			{
				cout << vecsEdges[i][j].first << ' ' << vecsEdges[i][j].second << ' ';
			}
			cout << endl;
		}*/

		vector<pair<int, int>> vecCounts(n, make_pair(INT_MAX, INT_MAX)); // pair(int count, int vec)
		for (size_t i = 0; i < n; i++)
		{
			vecCounts[i] = make_pair(vecsEdges[i].size(), i);
		}

		sort(vecCounts.begin(), vecCounts.end(), PairIntIntCompareMin);
		if (vecCounts[0].first != 1)
		{
			cout << "The consruct MST is error" << endl;
			return -1;
		}

		/*for (size_t i = 0; i < vecCounts.size(); i++)
		{
			cout << vecCounts[i].first << ' ' << vecCounts[i].second << endl;
		}*/

		vector<pair<int, int>> heapdistVecsCountEq1;//pair(int dist, int vec)count==1
		for (size_t i = 0; i < n; i++)
		{
			if (vecCounts[i].first == 1)
			{
				int mind = INT_MAX;
				for (int j = 0; j < vecsEdges[vecCounts[i].second].size(); j++)
				{
					mind = min(mind, vecsEdges[vecCounts[i].second][j].first);
				}

				heapdistVecsCountEq1.push_back(make_pair(mind, vecCounts[i].second));
			}
			else
				break;
		}
		make_heap(heapdistVecsCountEq1.begin(), heapdistVecsCountEq1.end(), PairIntIntCompareMin);

		/*for (size_t i = 0; i < heapdistVecsCountEq1.size(); i++)
		{
			cout << heapdistVecsCountEq1[i].first << ' ' << heapdistVecsCountEq1[i].second << endl;
		}
		cout << heapdistVecsCountEq1.front().first << ' ' << heapdistVecsCountEq1.front().second << endl;*/

		vector<bool> binSel(n, true);
		vector<int> minSteps(n, 0);
		minSteps[n-1] = MinStep(X, Y, binSel, n);
		/*cout << "minStep " << n << " : " << minSteps[n-1] << endl;*/
		for (int i = n-2; i >= 1; i--)
		{
			pair<int, int> maxdistvec = heapdistVecsCountEq1.front();

		/*	cout << "==== " << i << " ======" << endl;
			for (size_t s = 0; s < heapdistVecsCountEq1.size(); s++)
			{
				cout << heapdistVecsCountEq1[s].first << ' ' << heapdistVecsCountEq1[s].second << endl;
			}
			cout << "+++++++ " << endl;
			for (int s = 0; s < n; s++)
			{
				for (int p = 0; p < vecsEdges[s].size(); p++)
				{
					cout << vecsEdges[s][p].first << ' ' << vecsEdges[s][p].second << ' ';
				}
				cout << endl;
			}
			cout << "----" << endl;
			cout << maxdistvec.first << ' ' << maxdistvec.second << endl;*/


			binSel[maxdistvec.second] = false;
			minSteps[i] = MinStep(X, Y, binSel, i+1);
	/*		cout << "minStep " << i+1 << " : " << minSteps[i] << endl;*/

			pop_heap(heapdistVecsCountEq1.begin(), heapdistVecsCountEq1.end(), PairIntIntCompareMin);
			heapdistVecsCountEq1.pop_back();
			/*cout << "==== " << i << " ======" << endl;
			for (size_t s = 0; s < heapdistVecsCountEq1.size(); s++)
			{
				cout << heapdistVecsCountEq1[s].first << ' ' << heapdistVecsCountEq1[s].second << endl;
			}*/

			for (int j = 0; j < vecsEdges[vecsEdges[maxdistvec.second][0].second].size(); j++)
			{
				if (vecsEdges[vecsEdges[maxdistvec.second][0].second][j].second == maxdistvec.second)
				{ 
					vecsEdges[vecsEdges[maxdistvec.second][0].second].erase(vecsEdges[vecsEdges[maxdistvec.second][0].second].begin()+j);
					break;
				}

			}
			if (vecsEdges[vecsEdges[maxdistvec.second][0].second].size() == 1)
			{
				heapdistVecsCountEq1.push_back(make_pair(vecsEdges[vecsEdges[maxdistvec.second][0].second][0].first, vecsEdges[maxdistvec.second][0].second));
				push_heap(heapdistVecsCountEq1.begin(), heapdistVecsCountEq1.end(), PairIntIntCompareMin);
			}
			vecsEdges[maxdistvec.second].pop_back();

		}

		
		
		for (int i = 0; i < n-1; i++)
		{
			cout << minSteps[i] << ' ';
		}
		cout << minSteps[n - 1] << endl;

	}

	return 0;
}


实验结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值