poj 2008 Moo University - Team Tryouts 解题报告2

上一篇根据其他博主的算法,对该题进行了详细的剖析,但原来自己的算法一直都超时,经过修改,终于Time: 938MS 过了,泪奔,代码如下:

 

//具体思路:对h进行递增排序,固定h,再对每个w进行扫描,即可扫描得到结果,但超时,需要进行改进

//根据 A * H + B * W <= A * h + B * w + C,其中 A * H + B * W是不可能改变的,故对其进行递增排序,

//在比较期间,因为h是不变的,w是递增的,所以A * h + B * w + C是递增的,可以根据上一断点进行比较,剪掉了没有意义的比较

//但每次w比较完毕,在进行下一次w比较时,需要减去原来w的数量,因为w是递增的,而小于w是无法参加比赛的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_N 1024

typedef struct _calf {
    int w, h, k;
}calf;

int n, a, b, c, ans, cnt;
calf gcalf[MAX_N], calf_h[MAX_N], calf_w[MAX_N];

int cmp_w(const void *a, const void *b)
{
	return (((calf *)a)->w - ((calf *)b)->w);
}

int cmp_h(const void *a, const void *b)
{
	return ((calf *)a)->h - ((calf *)b)->h;
}

int cmp_k(const void *a, const void *b)
{
	return ((calf *)a)->k - ((calf *)b)->k;
}

void input()
{
	int i;
	for (i = 0; i < n; ++i)
	{
		scanf("%d %d", &gcalf[i].h, &gcalf[i].w);
		gcalf[i].k = a * gcalf[i].h + b * gcalf[i].w;
	}
	memcpy(calf_h, gcalf, n * sizeof(calf));
}

int main()
{
	scanf("%d %d %d %d", &n, &a, &b, &c);
	input();
	qsort(gcalf, n, sizeof(calf), cmp_k);
	qsort(calf_h, n, sizeof(calf), cmp_h);
	memcpy(calf_w, calf_h, n * sizeof(calf));

	ans = 0;
	int i, j, k, m, t, w(0), h(0);

	for (i = 0; i < n; ++i)
	{
		if(h == calf_h[i].h) continue;
		
		h = calf_h[i].h;
         //h固定,进行w排序
 		qsort(calf_w + i, n - i, sizeof(calf), cmp_w);

		w = 0;
		k = 0;
		cnt = 0;
		
		for (j = i; j < n; ++j)
		{
			if(w == calf_w[j].w) continue;
			if(n - j < ans) break;
			w = calf_w[j].w;
			t = a * h + b * w + c;
              //获取符合条件的小牛
			for (;  k < n; ++k)
			{
				if(gcalf[k].k > t) break;
				else if(gcalf[k].h >= h && gcalf[k].w >= w)	++cnt;
			}
			if(ans < cnt) ans = cnt;
              //减去 w 的小牛,因为下一次增加了w之后,本次w的小牛必须剔除
			for(m = 0; m < k; ++m)
			{
				if(gcalf[m].w == w && gcalf[m].h >= h && gcalf[m].k <= t) --cnt;
			}
		}

		memcpy(calf_w + i, calf_h + i, (n - i) * sizeof(calf));
	}
	printf("%d\n", ans);
	return 0;
}

整个算法刚刚卡在1000ms内,有点运气,感觉是每次的快排造成的原因,故想了办法去掉了排序,提高了200ms,也算是有所得吧, 下一次是 Time: 766MS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_N 1024

typedef struct _calf {
    int w, h, k;
}calf;

int n, a, b, c, ans, cnt;
calf gcalf[MAX_N], calf_h[MAX_N], calf_w[MAX_N];

int cmp_w(const void *a, const void *b)
{
	return (((calf *)a)->w - ((calf *)b)->w);
}

int cmp_h(const void *a, const void *b)
{
	return ((calf *)a)->h - ((calf *)b)->h;
}

int cmp_k(const void *a, const void *b)
{
	return ((calf *)a)->k - ((calf *)b)->k;
}

void input()
{
	int i;
	for (i = 0; i < n; ++i)
	{
		scanf("%d %d", &gcalf[i].h, &gcalf[i].w);
		gcalf[i].k = a * gcalf[i].h + b * gcalf[i].w;
	}
	memcpy(calf_h, gcalf, n * sizeof(calf));
}

int main()
{
	scanf("%d %d %d %d", &n, &a, &b, &c);
	input();
	qsort(gcalf, n, sizeof(calf), cmp_k);
	qsort(calf_h, n, sizeof(calf), cmp_h);
	memcpy(calf_w, calf_h, n * sizeof(calf));
    //对整个w进行一次排序
	qsort(calf_w, n, sizeof(calf), cmp_w);
	ans = 0;
	int i, j, k, m, t, w(0), h(0);

	for (i = 0; i < n; ++i)
	{
		if(h == calf_h[i].h) continue;
		
		h = calf_h[i].h;
          //不需要每次都排序了
//  		qsort(calf_w + i, n - i, sizeof(calf), cmp_w);

		w = 0;
		k = 0;
		cnt = 0;
		//每次都从0开始
		for (j = 0; j < n; ++j)
		{
              //在此对 <= w 或者 < h 的小牛进行剪枝,否则比刚才还费时
			if(w >= calf_w[j].w || h > calf_w[j].h) continue;
			if(n - j < ans) break;
			w = calf_w[j].w;
			t = a * h + b * w + c;
			for (;  k < n; ++k)
			{
				if(gcalf[k].k > t) break;
				else if(gcalf[k].h >= h && gcalf[k].w >= w)	++cnt;
			}
			if(ans < cnt) ans = cnt;
			for(m = 0; m < k; ++m)
			{
				if(gcalf[m].w == w && gcalf[m].h >= h && gcalf[m].k <= t) --cnt;
			}
		}
// 		memcpy(calf_w + i, calf_h + i, (n - i) * sizeof(calf));
	}
	printf("%d\n", ans);
	return 0;
}

感觉如果还要快的话,可以对 m 循环那个做个精简,应该是用空间换取时间的做法,将每次为w的东东存储起来,那样应该能快很多,今天就写到这里, 欢迎拍砖
posted @ 2011-12-03 15:33  Anbit自由之路  阅读(398)  评论(0编辑  收藏  举报