1. 程式人生 > >有n根長度不同的木棒,隨意選取三根湊一個合法的三角形,求總拼湊方案的數量(2018騰訊軟體開發-後臺開發方向秋招補考試題第三題)

有n根長度不同的木棒,隨意選取三根湊一個合法的三角形,求總拼湊方案的數量(2018騰訊軟體開發-後臺開發方向秋招補考試題第三題)

題目:

有n根長度不同的木棒,隨意選取三根湊一個合法的三角形,求總拼湊方案的數量。對於兩個方案,只要有一根木棒的長度不同,則視為不同拼湊方案。

輸入描述

第一行為正數t(0 <= t <= 10),表示測試用例數

接下來每兩行一個測試資料,第一行一個整數n(3 <= n <= 2000)表示木棒數量

第二行n個不一樣的正整數li(1 <= li <= 10^9),表示每根木棒的長度。

輸入描述

對於每一個測試用例,輸出一個正整數表示方案數

示例

2 4 14 21 94 35 6 10 16 87 43 51 75  

程式碼

using namespace std;

typedef unsigned int T;

int triangle_nums(T* data, int size)
{
	int counts = 0;
	sort(data, data + size);
	for (int x = 0; x < size-2; ++x){
		for (int y = x + 1; y < size - 1; ++y){
			T xy = data[x] + data[y];
			for (int z = y + 1; z < size; ++z){
				if (xy > data[z]){
					//if ((data[z] + data[x]) > data[y] && (data[z] + data[y]) > data[x])
						++counts;
				}
				else{
					break;
				}
			}
		}
	}
	return counts;
}

int main(int argc, char** argv)
{
	int t;
	int n;
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> t;
	if (t < 1 || t > 10)
		return 0;
	T* l = new T[2000];
	while (t--){
		cin >> n;
		if (n < 3 || n > 2000){
			delete[]l;
			return 0;
		}
		for (int i = 0; i < n; ++i)
			cin >> l[i];
		cout << triangle_nums(l, n) << endl;
	}
	delete[]l;
	return 0;
}

一開始使用暴力求解,三層遍歷,然後x+y>z&&y+z>x&&x+z>y。但複雜度太大,達到了n^3,後面超出時間,只通過了50%。後來想到了先從小到大排序(時間複雜度nlog(n))。再進行x+y>z,這樣只要某個z不滿足條件,後續的z也肯定不滿足,就可以提前退出。修改後增加到60%左右,同樣出現了超時,完全沒轍了。最後一分鐘仔細思考發現,如果是已經排序了的,只要確保x+y>z就可以,因為y+z>x&&x+z>y這個時候是肯定滿足的。最後註釋掉程式碼中的一個if就100%了。