POJ1456 Supermarket 贪心 DP

题意:

给定一批product,每个product有相应的profit和deadline,销售出一个product需要1单位的时间。

问如何销售这些商品可以使获得的利润最大。


思路:

贪心算法。

但是首先有一个误区需要注意:

每个商品的deadline,比如d=5,这个参数表明的是从1到5这个时间内都可以销售这个商品。

比如有:

d=2,p=20;

d=2,p=30;

d=1,p=2;

这样三个商品。

则销售最大值是50,而不是32。

理解这点之后其实就很直观了:

拿例子说:

7
20 1
2 1
100 2
80 2
10 3
50 10
5 20

定义数组dp[N];

整个动态规划的过程就是对dp数组进行填充。比如d=3的product可以填充在d[1],dp[2],dp[3]中的任何一个。

因为要使利润最大,则使用贪心。

所以,

当取到 20 1时,dp[1]=20 .

取到2 1时,因为2<20,舍弃不用。

当取到100 2时,将其填在dp[2]肯定是满足利润最大的情况。

而取到80 2时,将其填在dp[1]还是舍弃呢?因为80大于之前dp[1]=20。所以修改dp[1]=80。

依此类推,其实很简单,并查集都不需要用到也是可以AC的。

#include<iostream>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
const int N=10005;
int n,ans;
struct Node
{
	int p,d;
}node[N];
int dp[N];
int mn,mpos;
bool cmp(Node & a,Node & b)
{
	if((a.d<b.d)||(a.d==b.d&&a.p>b.p))
		return true;
	return false;
}
void UpdateMin(int x)
{
	int tmp1=-1,tmp2=N;
	for(int j=1;j<=x;j++)//更新最小值
	{
		if(tmp2>dp[j])
		{
			tmp2=dp[j];
			tmp1=j;
			if(!tmp2)
				break;
		}
	}
	mpos=tmp1;
	mn=tmp2;
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		ans=0,mn=N,mpos=-1;
		memset(node,0,sizeof(node));
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			scanf("%d%d",&node[i].p,&node[i].d);
		}
		sort(node+1,node+1+n,cmp);
		ans+=node[1].p;
		dp[node[1].d]=node[1].p;
		UpdateMin(node[1].d);
		for(int i=2;i<=n;i++)
		{
			if(node[i].d!=node[i-1].d)
			{
				dp[node[i].d]=node[i].p;
				ans+=node[i].p;
			}
			else if(node[i].p>mn)
			{
				ans+=node[i].p-mn;
				dp[mpos]=node[i].p;
			}
			UpdateMin(node[i].d);
		}
		printf("%d\n",ans);
	}
	
	return 0;
}


你可能感兴趣的:(算法)