Sunscreen(poj3624)与Task(HDOJ4864)的比较-贪心

Sunscreen

要找最多的奶牛,所以从奶牛的角度考虑问题。将奶牛的min从大到小排序,对于每个奶牛,要找满足他条件的里面的防晒霜之中spf最大的。因为后面的奶牛的min一定小于等于这个奶牛,下线不成问题,而只关乎上线,我们要把上线小的尽量留到后面。

#include <bits/stdc++.h>

using namespace std;
const int maxn=3005;
int c,l;
struct cow
{
	int minv,maxv;
}a[maxn];
struct sth
{
	int spf,cover;
}b[maxn];
int cmp(cow x,cow y)
{
	return x.minv>y.minv;
}
int cmp1(sth x,sth y)
{
	return x.spf>y.spf; 
}
int main()
{
	scanf("%d%d",&c,&l);
	for(int i=1;i<=c;i++)
	{
		scanf("%d%d",&a[i].minv,&a[i].maxv);
	}
	for(int i=1;i<=l;i++)
	{
		scanf("%d%d",&b[i].spf,&b[i].cover);
	}
	sort(a+1,a+1+c,cmp);
	sort(b+1,b+1+l,cmp1);
	int cnt=0;
	for(int i=1;i<=c;i++)
	{
		for(int j=1;j<=l;j++)
		{
			if(b[j].cover&&b[j].spf>=a[i].minv&&b[j].spf<=a[i].maxv)
			{
				b[j].cover--;cnt++;
				break;
			}
		}
	}
	printf("%d",cnt);
	return 0;
}

Task

因为是要选最多的任务,我么可以从任务的角度考虑。将所有机器和任务按照时间和价值都排序,逐个枚举每个任务。因为我们要尽可能多的满足完成最多的任务,所以对于每个任务,我们要选取比他时间大的中的价值最小的。(因为我们排了序,所有后面所有的任务在时间这一方面一定满足要求)

如果学习上一题的话我们应当枚举每个机器,但这样会超时。而根据观察,我们发现总共可能的价值总是非常小,我们可以用存下所以价值出现的个数,然后每次找最小的那个就行了。(当然上一题也可以这样写啊)

PS:还有一个问题,会不会存在某个任务时间比较短,但是价值很大而导致其可以的贡献大于某个时间比他大一点点却价值小很多的任务呢?

答案是不会的。因为数据范围限制y<=100,即使价值是0和100的差距,时间是1的差距,那么1*500>100*2,所以只有在时间相同的情况下才考虑价值的优先级。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=100005;
int n,m,num[120]; 
struct node
{
	int x,y;
}a[maxn],b[maxn];
int cmp(node x1,node x2)
{
	if(x1.x!=x2.x) return x1.x>x2.x;
	return x1.y>x2.y;
}
void work()
{
	memset(num,0,sizeof(num));
	for(int i=1;i<=n;i++)//machine
	{
		scanf("%d%d",&a[i].x,&a[i].y);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&b[i].x,&b[i].y);
	}
	sort(a+1,a+1+n,cmp);
	sort(b+1,b+1+m,cmp);
	int j=1; ll cnt=0;int ans=0;
	for(int i=1;i<=m;i++)//按时间从大到小枚举任务 
	{
		//要选x满足条件时y最低
		while(j<=n&&b[i].x<=a[j].x) {num[a[j].y]++;j++;}
		for(int tot=b[i].y;tot<=100;tot++)
		{
			if(num[tot])
			{
				num[tot]--;ans++;
				cnt+=1ll*500*b[i].x+b[i].y*2;
				break;
			}	
		} 
	}
	printf("%d %lld",ans,cnt);
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		work();
	}
	return 0;
 } 

总结:2道题都是2中不同物品的最大匹配个数问题,并且有被匹配物有2个关键字需要被满足,我们都是按照先保证满足一个关键字的原则下再去贪心。保证当前物品能被选中的情况下(不选白不选)尽量让更好的第二关键字能留给后面用。

要求哪个东西最多就对哪个东西贪心。

而第二题在保证第一个的条件下多了一个限制其实是纸老虎,只是多加一个排序关键字而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章