阿里 2020暑期實習生 筆試回憶

題型

  • 編程 2道 60min

編程1: 修水渠

給若干點的座標,代表每一個村子,現在要修一條平行於y軸且無限長的水渠,求所有村莊距離這條水渠垂直長度之和的最小值。

  • 輸入:n代表村莊的個數,接下來n行,每行2個數,代表村莊的座標,x>=0,y<=10000
  • 輸出:一個數,代表最小距離
  • 思路:想了一下好像和縱座標沒關係,然後拿筆試了試,認定水渠的x值必是和某一村莊的x相同(感覺有點被給出的樣例誤導),然後就開始了錯誤的解題過程。。。
    後來想了一下,暴力解的話,可以從最左邊的村莊位置開始,不斷x+=1遍歷到最右邊的村莊位置,得到最小距離,優化的話,在第i-1和第i個村莊之間的距離,dis = dis - ( n - i ) + i,即dis = dis + 2i -n,每向右增加一各單位距離,左邊的所有村莊距離水渠位置都+1,右邊的所有村莊距離水渠位置都-1 。
    找幾個用例手工算的話,發現如果村莊的數量是奇數,就選中間的村莊,是偶數,就選第n/2和第n/2+1個村莊之間的任意位置,實際上這兩個村莊的位置也是最小位置,這麼說來不論怎麼選最小位置還是在某個村莊的位置,那麼問題來了,爲什麼沒有通過測試用例。。。忘記排序了。。。想哭
#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>
#include<cmath>

using namespace std;

int main(){
	int n;
	cin >> n ;
	vector<int> x(n);
	vector<int> y(n);
	for (int i = 0; i < n; i++)
		cin >> x[i] >> y[i];
	//初始化長度
	int curr = 0, minVal = INT_MAX;
	sort(x.begin(), x.end());
	for (auto a : x)
		curr += (a - x[0]);
	for (int i = 1; i < n; i++)
	{
		curr = curr + i*(x[i] - x[i - 1]) - (n - i)*(x[i] - x[i - 1]);
		minVal = min(minVal, curr);
	}
	cout << minVal;
	system("pause");
	return 0;
}

編程2:塗色

給定一個n*m的矩陣,給定c種顏色的染料,以及每種染料的數量,試問是否有一種方法給矩陣染色,使得每個方塊的與他上下左右的顏色均不同。

  • 輸入:n,m,c,接下來一行c個數,代表每種染料的數量
  • 輸出:YES或NO
  • 思路:當時看到一眼想起一個什麼定律,如果有3種還是4種不同顏色的染料對什麼東西進行染色,必可以滿足相鄰位置不同色。
    其實當時也想到了遞歸,但總覺得遞歸會超時,就沒寫。。。當時想的是按照斜線的方式遍歷矩陣,從第一個顏色開始按順序往下塗,遍歷完能塗完就輸出YES,真是智障實錘了,考完了想了想,這不就是八皇后的翻版嗎。。。直接遞歸就完事了

代碼寫的比較菜。。。但應該可以AC一部分吧。。。
遞歸的結束條件和裏面的循環可能寫的不是很好,會增加一些運行時間

#include<iostream>
#include<vector>

using namespace std;

void recurse(vector<vector<int>> &map, vector<int> col, int x, int y);

bool tag = false;

int main(){
	int n, m, c;
	cin >> n >> m >> c;
	vector<int> col(c);
	for (auto &a: col)
	{
		cin >> a;
	}
	vector<vector<int>> map(n, vector<int>(m, -1));
	recurse(map, col, 0, 0);
	cout << (tag ? "YES" : "NO");
	system("pause");
	return 0;
}

void recurse(vector<vector<int>> &map, vector<int> col, int x, int y)
{
	if (tag) return;
	if (y >= map[0].size())
	{
		y = 0;
		x++;
	}
	if (x >= map.size())
	{
		tag = true;
		return;
	}
	for (int i = 0; i < col.size(); i++)
	{
		if (y - 1<0 || (col[i] > 0 && map[x][y - 1] != i))
		if (x - 1<0 || (col[i] > 0 && map[x - 1][y] != i))
		{
			map[x][y] = i;
			col[i]--;
			recurse(map, col, x, y + 1);
			col[i]++;
			map[x][y] = -1;
		}
	}
}

筆試的時候時間的影響實在是太大了,完全不敢認真的去思考,還有對測試用例的無序性一定要記住,該遞歸就遞歸,先作出來再說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章