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個關鍵字需要被滿足,我們都是按照先保證滿足一個關鍵字的原則下再去貪心。保證當前物品能被選中的情況下(不選白不選)儘量讓更好的第二關鍵字能留給後面用。

要求哪個東西最多就對哪個東西貪心。

而第二題在保證第一個的條件下多了一個限制其實是紙老虎,只是多加一個排序關鍵字而已。

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