POJ - 1065 Wooden Sticks 贪心+最长上升子序列

题目:http://poj.org/problem?id=1065

大意:

有N根木棍等待处理。机器在处理第一根木棍时需要准备1分钟,此后遇到长宽都不大于前一根木棍的木棍就不需要时间准备,反之则需要1分钟重新准备。比如木棍按照(3,3)、(1,3)、(1,4)、(2,3)的顺序进入,共需要准备3分钟

 

思路:  看数据,n<=5000, 长重都<=10000,是否需要重新准备依赖于长和重,但是假如将长和重都作为变量放入dp数组内,数组的大小将会达到10^8次方,再加上5000的n数据量,内存装不下,假如要对dp数组作遍历,即使是On的算法也会超时。

因此需要减少状态的量,顺着这个思路就想到了先预处理所有木棍。因为没有规定木棍需要按顺序放入,假如先将木棍按照长或者重升序排列,那么我们选择的时候就不需要再关注该变量了。

排序完之后题目就转化成了最长上升子序列的问题,也就是最少选择多少个上升子序列使得所有木棍都被选择完毕。

#include
#include
#include
#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn1 = 5000 + 5;
const int maxn2 = 10000 + 5;
struct node {
	int x, y;
}num[maxn1];
int len[maxn1];
bool cmp(node a, node b) {
	if (a.x != b.x) return a.x < b.x;
	else return a.y < b.y;
}
int main() {
	int T; cin >> T;
	while (T--) {
		int n; cin >> n;
		for (int i = 1; i <= n; i++) {
			scanf("%d %d", &num[i].x, &num[i].y);
		}
		sort(num + 1, num + 1 + n, cmp);
		int cnt=0,res=0;
		while (cnt < n) {
			res++;
			memset(len, 0, sizeof(len));
			int maxx = 0;
			for (int i = 1; i <= n; i++) {
				if (num[i].y==0) continue;
				if (len[maxx] <= num[i].y) {
					len[++maxx] = num[i].y;
					cnt++;
					num[i].y = 0;
				}
				else {
					int flag = lower_bound(len, len + 1 + n, num[i].y) - len;
					len[flag] = num[i].y;
				}
			}
		}
		cout << res << endl;
	}
	return 0;
}

 

你可能感兴趣的:(acm)