进阶之路

首页 新随笔 管理

 计算机 1s 的计算能力:1000 000 次, 游刃有余; 10 000 000,勉强; 100 000 000,很悬,一般不能。   

1.1 抽签

有 n 张纸片, 每个纸片上一个任意数字 ki 。取出 1 张,记下数字后放回,取 4 次。如果 4 个数字的和是 m, 则赢。给定一个 m, 判断是否有赢的可能性 (输出 Yes or No)。

 Limits : (1 <= n <= 1000, 1 <= m <= 108, 1<= ki <= 108)

样例1:输入:n = 3, m = 10, k = {1, 3, 5}     输出: Yes (如:1, 1, 3, 5)

样例2:输入:n = 3, m = 9, k = {1, 3, 5}     输出: No (不存在)

思路: 若递归四次: 10004 >> 109, 肯定超时,故此方法不可取。

优化方法:任意两个的和共 n2 个, 只要从 n2 个数中找到有没有两个数的和为 m 即可。同时,对这 n2 个数排序,利用二分查找求解。

时间复杂度: O(N2logN)

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

int main () {
	int n, m;
	cin >> n >> m;
	vector<int> k(n);
	vector<int> sum(n*n);
	for (int i = 0; i < n; ++i) cin >> k[i];
	/**********************************************************/
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			sum[i*n+j] = k[i] + k[j];
		}
	}
	sort(sum.begin(), sum.end());
	bool exist = false;
	for(int i = 0; i < n; ++i) {
		if (binary_search(sum.begin(), sum.end(), m-sum[i])) {
			exist = true;
			break;
		}
	}
	if(exist) cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}

 1.6.1 三角形 

有 n 根棍子,棍子 i 长度 ai, 选出 3 根组成周长尽可能长的三角形。输出最大周长,若无法组成三角形则输入为 0。

Limits: (3 <= n <= 100000, 1 <= ai <= 106)

样例1: 输入: n = 5, a = {2, 3, 4, 5, 10}   输出:12 (3, 4, 5)

样例2: 输入: n = 4, a = {4, 5, 10, 20}     输出: 0 

思路: 假设 a <= b <= c。只要满足 a + b > c 即可组成三角形。

因此,2b > c ,对每个 A[i] (即 b) 只要在有序数组 A 中找出小于 2b 的第一个元素 c , 若其满足 c - b < a (即 A[i-1]), 则组成一个以 A[i] 为中间长度的边的周长最大的三角形, 否则若是 c - b >= a (即 A[i-1]), 则不存在以 A[i] 为中间边的三角形。 时间复杂度 : O(NlogN)

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

int binary_find (vector<int>& A, int L, int H, int value) {
	if (A[H] < value) return A[H];
	while (L <= H) {
		int mid = (L+H) >> 1;
		if (A[mid] >= value) H = mid-1;
		else if (A[mid+1] >= value) 
			return A[mid];
		else L = mid + 1;
	}
	return 0;
}

int main () {
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; ++i) cin >> a[i];
	/********************************************************/
	sort(a.begin(), a.end());
	int ans = 0;
	for (int i = n-2; i > 0; --i) {
		int c = binary_find(a, i+1, n-1, a[i] << 1);
		if ( c && c < a[i] + a[i-1]) {
			ans = c + a[i] + a[i-1];
                        break;
		}
	}
	cout << ans << endl;
	return 0;
}

1.6.2 Ants (蚂蚁)

n 只蚂蚁以 1cm/s 的速度在长为 Lcm 的竿子上爬行,爬到端点掉落。竿子很细,导致蚂蚁相遇时只能反向爬回。每只蚂蚁距离竿子左端距离 xi, 但不知其朝向。计算所有蚂蚁落下竿子的最短时间和最长时间。

Limits: (1 <= L <= 106, 1 <= n <= 106, 0 <= xi <= L)

样例:输入: L = 10, n = 3, x = {2, 6, 7}    输出: min = 4 (左、 右、 右)

思路:由于蚂蚁都相同,所以两只蚂蚁相遇后交错而过和反向爬回是一样的。所以,可以看成每只蚂蚁是独立运动的。

void solve(int x[], int n, int L) {
	int minT = 0, maxT = 0;
	for (int i = 0; i < n; ++i) {
		minT = max(minT, min(x[i], L - x[i]));
		maxT = max(maxT, max(x[i], L - x[i]));
	}
	cout << minT << endl << maxT << endl;
}

 

posted on 2014-09-30 16:09  进阶之路  阅读(251)  评论(0编辑  收藏  举报