牛客網-華為-2020屆校園招聘上機考試-3


題目描述
小明在玩切水果游戲,已知屏幕上有若干水果,只允許用直線切水果,一次只允許划出一條直線,直線上的水果都會被消除掉;請求出小明最少要切多少次才能把屏幕上的水果都切掉。已知屏幕由40*50的小方格組成,經過每個方格划出的直線最多只有4條,如下圖所示經過紅色方格(標注為8)能划出直線最多為4條,其中相同數字的方格屬於同一直線(0為空);屏幕左上角坐標為(0,0),右下角坐標為(39,49)。
|4|0|0|1|0|0|3|
|0|4|0|1|0|3|0|
|0|0|4|1|3|0|0|
|2|2|2|8|2|2|2|
|0|0|3|1|4|0|0|
|0|3|0|1|0|4|0|
|3|0|0|1|0|0|4|

輸入描述
第一行輸入整數N(0<N<=36),接下來N行,每行兩個整數X,Y(0<=X<40, 0<=Y<50)用空格隔開,表示水果所在方格的X坐標和Y坐標,不同水果的坐標一定不同,輸入保證合法。
輸出描述
程序輸出一個整數並換行,表示小明需要切水果的最少次數。

示例1
輸入
2
3 4
2 2
輸出
2

1.思考

  • 本來是放棄第二題先做第三題的,結果發現第三題更難,只好硬着頭皮寫了……
  • 先用coor記錄下所有水果的位置坐標;
  • 再用一個map表示每個位置的水果在橫切、豎切、左上至右下切、右上至左下切四種方式下能夠切到的其他的水果的id,這里的id直接就用輸入先后順序作為id;
  • 然后用一個count記錄每個位置的水果在一刀下能切掉水果的最多數目;
  • 接着每次都選擇能夠切掉最多水果的那個位置下的那一刀,並將已經切掉的水果從coor記錄中刪除;
  • 之后依照新的coor記錄重新建立map和count,重復上述過程,直至所有水果都消除。
  • 因為沒有線上提交,所以不太清楚這個方案是否能通過所有的測試集。我主要困惑的是,每次選擇能切掉最多水果的那一刀,是否能夠保證最后用的次數是最少的,這一點還沒有想通,所以有可能思路是錯誤的,代碼也寫的不對……

2.實現

#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;

vector<vector<vector<int>>> map;

void Hori(int index, vector<vector<int>> coor)
{
	vector<int> co = coor[index];
	int len = coor.size();
	for (int i = 0; i < len; i++){
		if (i != index){
			auto node = coor[i];
			if (node[1] == co[1]){//same y label -
				map[index][0].push_back(i);
			}
		}
	}
}

void Vert(int index, vector<vector<int>> coor)
{
	vector<int> co = coor[index];
	int len = coor.size();
	for (int i = 0; i < len; i++){
		if (i != index){
			auto node = coor[i];
			if (node[0] == co[0]){//same x label |
				map[index][1].push_back(i);
			}
		}
	}
}

void Left(int index, vector<vector<int>> coor)
{
	vector<int> co = coor[index];
	int len = coor.size();
	for (int i = 0; i < len; i++){
		if (i != index){
			auto node = coor[i];
			if (node[0]-node[1]==co[0]-co[1]){//From top left to bottom right \
				map[index][2].push_back(i);
			}
		}
	}
}

void Right(int index, vector<vector<int>> coor)
{
	vector<int> co = coor[index];
	int len = coor.size();
	for (int i = 0; i < len; i++){
		if (i != index){
			auto node = coor[i];
			if (node[0] + node[1] == co[0] + co[1]){//From top right to bottom left /
				map[index][3].push_back(i);
			}
		}
	}
}

//Calculate the max number of fruits when erase fruit i.
void CalMaxCount(vector<int>& count)
{
	int n = map.size();
	int maxc = 0;
	for (int i = 0; i < n; i++){
		auto m = map[i];
		maxc = 0;
		for (int j = 0; j < 4; j++){
			int lm = m[j].size();
			maxc = maxc>lm?maxc:lm;
		}
		count[i] = maxc;
	}
}

vector<int> ConstMap(int n, vector<vector<int>>& coor)
{
	map.clear();

	//initial map
	vector<int> a;
	vector<vector<int>> b;
	for (int i = 0; i < 4; i++){
		b.push_back(a);
	}
	for (int i = 0; i < n; i++){
		map.push_back(b);
	}

	int lc = coor.size();
	vector<int> count(n);
	for (int i = 0; i < lc; i++){
		Hori(i, coor);
		Vert(i, coor);
		Left(i, coor);
		Right(i, coor);
	}
	CalMaxCount(count);

	return count;
}

bool cmp(int a, int b)
{
	return a > b;
}

void CoorClear(int index, vector<vector<int>>& coor)
{
	int len = coor.size(), pos = 0, maxc = 0;
	auto m = map[index];
	for (int j = 1; j < 4; j++){
		if ( m[j].size() > maxc ){
			maxc = m[j].size();
			pos = j;
		}
	}

	vector<int> node = map[index][pos];
	sort(node.begin(), node.end(), cmp);
	for (int i = 0; i < maxc; i++){
		coor.erase(coor.begin()+node[i]);
	}
	coor.erase(coor.begin() + index);
}

int main(){
	int n;

	while (cin>>n){
		int x, y;
		vector<vector<int>> coor;
		vector<int> count(n);

		//input coordinate
		for (int i = 0; i < n; i++){
			cin >> x >> y;
			coor.push_back(vector<int> {x, y});
		}

		int res = 0, pos;
		while(coor.size()){
			//Construct Map
			count = ConstMap(n, coor);

			//Erase the line with most fruits.
			pos = max_element(count.begin(), count.end()) - count.begin();
			CoorClear(pos, coor);
			res++;
		}

		cout << res<<endl;
	}

	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM