现在的位置: 首页 > 综合 > 正文

POJ3497 Assemble 二分+贪心

2013年05月21日 ⁄ 综合 ⁄ 共 3907字 ⁄ 字号 评论关闭

Problem Address:http://poj.org/problem?id=3497

【前言】

昨天写了这道题的代码,交了返回CE。

一看发现POJ又崩溃了= =

后来又写多了一道。

今天回到学校,重新交了这两道题。

前者返回TLE,后者返回AC。

于是乎改啊改,不知道哪里TLE了,质疑二分写的不好。

很多次TLE后,修改了代码,改成map之类的,还是TLE。

最后找到某份代码,抄了个二分,然后就A掉了。

发现自己还是很不会写二分外面的那个东东,加一减一大于小于控制不好。

大概200+ms。

后来提交了第一次的代码,发现居然100+ms!

【思路】

题意:电脑的性能由其组件中性能最差的那一个决定,要求最大性能。

思路就是二分这个性能,然后对于每一个组件,找出其中大于这个性能的最小价格,累加起来。

如果不超过预算,则符合条件。

由于题意所给数据已排好序,所以可以省去排序一步。

对于每一个组件,可以先预处理好大于其quality的最小price,此后便无须重复判断。

200+的代码是把同类的组件放在同一个数组里。用map映射。

100+的代码是直接不修改,记录每一个组件在数组中的范围,然后查找的时候通过这些区间查找即可。

我觉得时间差距应该还是在map上。

此外,由于每个组件的个数并不是特别多,所以即使在查找组件中符合条件的个数时进行二分,效果也不是特别明显的。

【代码】

200+ms:

#include <iostream>
#include <algorithm>
#include <string>
#include <map>
using namespace std;

const int maxn = 1000;

map<string, int> map_index;

struct component
{
	int price;
	int quality;
	int min_price;
}p[maxn+5][maxn+5];
int p_ct[maxn+5];

int seg[maxn+5][2];

bool cmp(const component &a, const component &b)
{
	if (a.quality!=b.quality) return a.quality<b.quality;
	else return a.price<b.price;
}

bool solve(int q, int b, int ct)
{
	int i, j;
	int sum = 0;
	for (i=0; i<ct; i++)
	{
		for (j=0; j<p_ct[i]; j++)
		{
			if (p[i][j].quality>=q)
			{
				sum += p[i][j].min_price;
				break;
			}
		}
//		int low = 0, high = p_ct[i]-1, mid;//注释部分为在组件内部二分
//		if (p[i][high].quality<q) return false;
//		while(low<high)
//		{
//			mid = (low+high)/2;
//			if (p[i][mid].quality>=q) high = mid;
//			else low = mid+1;
//		}
//		sum += p[i][high].min_price;
		if (j>=p_ct[i]) return false;
		if (sum>b) return false;
	}
	return true;
}


int main()
{
	int t;
	int n, b;
	int i, j;
	int c, d;
	char m_type[25], name[25];
	string x;
	int ct;
	int index;
	int high, low, mid;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d %d", &n, &b);
		memset(p_ct, 0, sizeof(p_ct));
		map_index.clear();
		ct = 0;
		high = -INT_MAX;
		low = INT_MAX;
		for (i=0; i<n; i++)
		{
			scanf("%s %s", m_type, name);
			x = "";
			for (j=0; m_type[j]!='\0'; j++)
				x += m_type[j];
			if (map_index.find(x)==map_index.end())
			{
				map_index[x] = ct;
				ct++;
			}
			index = map_index[x];
			scanf("%d %d", &c, &d);
			p[index][p_ct[index]].price = c;
			p[index][p_ct[index]].quality = d;
			if (d>high) high = d;
			if (d<low) low = d;
			p_ct[index]++;
		}
		for (i=0; i<ct; i++)
		{
		//	sort(&p[i][0], &p[i][p_ct[i]], cmp);//已排好序,可以不排
			p[i][p_ct[i]-1].min_price = p[i][p_ct[i]-1].price;
			for (j=p_ct[i]-2; j>=0; j--)
			{
				if (p[i][j].price<p[i][j+1].min_price)
					p[i][j].min_price = p[i][j].price;
				else
					p[i][j].min_price = p[i][j+1].min_price;
			}
		}
		int flag = 0;
		while(low<=high)
		{
			mid = (low+high)/2;
			if (solve(mid, b, ct))
			{
				low = mid+1;
				flag = 1;
			}
			else high = mid-1;
		}
		if (flag==0) printf("0\n");
		else printf("%d\n", high);
	}
	return 0;
}

100+ms:

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

const int maxn = 1000;

struct component
{
	char m_type[25];
	int price;
	int quality;
	int min_price;
}p[maxn+5];

int seg[maxn+5][2];

bool cmp(const component &a, const component &b)
{
	int t = strcmp(a.m_type, b.m_type);
	if (t<0) return true;
	else if (t>0) return false;
	else if (a.quality!=b.quality) return a.quality<b.quality;
	else return a.price<b.price;
}

bool solve(int q, int b, int ct)
{
	int i;
	int low, high, mid;
	int sum = 0;
	for (i=0; i<ct; i++)
	{
//		for (j=seg[i][0]; j<=seg[i][1]; j++)//函数内注释部分为非组件内部二分代码
//		{
//			if (p[j].quality>=q)
//			{
//				sum += p[j].min_price;
//				break;
//			}
//		}
		low = seg[i][0];
		high = seg[i][1];
		while(low<high)
		{
			mid = (low+high)/2;
			if (p[mid].quality>=q) high = mid;
			else low = mid+1;
		}
//		if (j>seg[i][1]) return false;
		if (p[high].quality<q) return false;
		sum += p[high].min_price;
		if (sum>b) return false;
	}
	return true;
}

int main()
{
	int t;
	int n, b;
	int i, j;
	char name[25];
	int ct;
	int high, low, mid;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d %d", &n, &b);
		for (i=0; i<n; i++)
			scanf("%s %s %d %d", p[i].m_type, name, &p[i].price, &p[i].quality);
//		sort(p, p+n, cmp);//省去排序
		memset(seg, 0, sizeof(seg));
		ct = 0;
		for (i=1; i<n; i++)
		{
			if (strcmp(p[i-1].m_type, p[i].m_type)!=0)
			{
				seg[ct][1] = i-1;
				ct++;
				seg[ct][0] = i;
			}
		}
		seg[ct][1] = n-1;
		ct++;
		for (i=0; i<ct; i++)
		{
			p[seg[i][1]].min_price = p[seg[i][1]].price;
			for (j=seg[i][1]-1; j>=seg[i][0]; j--)
			{
				if (p[j].price<p[j+1].min_price)
					p[j].min_price = p[j].price;
				else p[j].min_price = p[j+1].min_price;
			}
		}
		high = -INT_MAX;
		low = INT_MAX;
		for (i=0; i<n; i++)
		{
			if (p[i].quality>high) high = p[i].quality;
			if (p[i].quality<low) low = p[i].quality;
		}
		int flag = 0;
		while(low<=high)
		{
			mid = (low+high)/2;
			if (solve(mid, b, ct))
			{
				flag = 1;
				low = mid + 1;
			}
			else high = mid-1;
		}
		if (flag==0) printf("0\n");
		else printf("%d\n", high);
	}
	return 0;
}

【P.S】

为神马二分的函数总写不好%>_<%

抱歉!评论已关闭.