1. 程式人生 > 實用技巧 >poj1456 supermarket---貪心+並查集優化

poj1456 supermarket---貪心+並查集優化

題目連結:https://vjudge.net/problem/POJ-1456#author=yuming

題意:N個商品. 第i個商品必須在保質期第di天前賣掉, 若賣掉可獲得pi的利潤。每天只能賣一個商品,求最大利潤

主要想法還是貪心,一是儘量賣出利潤大的物品,二是物品儘量在靠近保質期的日期出售。於是先按照pi排序,之後按利潤從大到小考慮。對於當前的物品,如果保質期內有某天可以賣掉,就在最靠近保質期的那天賣掉,並且給那一天打上標記。要找到最靠近保質期的那天,可以直接暴力列舉,也可以用並查集優化,程式碼都很短

直接列舉(資料估計水了,125ms過)

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int maxn=1e4+10;
int t,n,i,j,k,u[maxn];
struct st{int p,d;}a[maxn];

bool cmp(st x,st y){return x.p>y.p;}

int main(){
	while (~scanf("%d",&n)){
	  for (i=1;i<=n;i++) scanf("%d%d",&a[i].p,&a[i].d);
	  sort(a+1,a+n+1,cmp);
	  memset(u,0,sizeof(u));
	  int ans=0;
	  for (i=1;i<=n;i++){
	  	for (j=a[i].d;j>=1;j--)
	  	  if (!u[j]){u[j]=1; break;}
	  	if (j) ans+=a[i].p;
	  }
	  printf("%d\n",ans);
	}
	return 0;
}

並查集優化:

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
int n,i,j,k,u[10010];
struct st{int p,d;}a[10010];

bool cmp(st x,st y){return x.p>y.p;}
int find(int x){return u[x]==-1?x:u[x]=find(u[x]);}

int main(){
	while (~scanf("%d",&n)){
	  for (i=1;i<=n;i++) scanf("%d%d",&a[i].p,&a[i].d);
	  sort(a+1,a+n+1,cmp);
	  memset(u,-1,sizeof(u));
	  int ans=0;
	  for (i=1;i<=n;i++){
	  	int k=find(a[i].d);  
	  	if (k){ans+=a[i].p; u[k]=k-1;}
	  }
	  printf("%d\n",ans);
	}
	return 0;
}