您的位置:首页 > 其它

POJ1456 Supermarket 贪心 DP

2012-01-22 14:44 411 查看
题意:

给定一批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
;

整个动态规划的过程就是对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
;
int dp
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: