Supermarket(贪心/并查集)
原创的博客
题意:
超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润。
每天只能卖一个商品。
现在你要让超市获得最大的利润。
n , p[i], d[i] 范围都在10000以内 。
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=4e5+5; int n; priority_queue<int>q; vector<int>v[N]; int main() { while(cin>>n) { for(int i=1;i<=10001;i++) v[i].clear() ; priority_queue<int>empty; swap(empty, q); //相当于清空q。 for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); v[y].push_back(x); } int ans=0; for(int i=10005;i>=1;i--) { for(int j=0;j<v[i].size();j++) { q.push(v[i][j]); } if(!q.empty()) { ans+=q.top(); q.pop(); } } printf("%d\n",ans); } }
用另一种贪心的方法来做,先把所有产品按照利润从大到小排序,然后这个把这个放在截止日期那天卖出,并做好标记,如果截至日期那天已经有其他产品占用了,那么可以把这个产品卖出的时间往前推,直到找到可以卖的那一天并标记好。 按照这种思路提交,AC了,不过却用了141 ms。
用了这个方法之后,再回想了下并查集方法的代码, 所谓的用并查集做,实际上是对上面那种方法的优化!
用并查集的关键之处是,我们知道按照上面那个方法,假设一个产品a占用了一个日期后,那么如果下次又有一个产品b和产品a的截止日期是相同的,但是那个日期以被占用了,所以就要往前移动1天,那么就可以用并查集进行标记,在a占用了那个日期后,把a的截止日期指向前一个日期,这样的话,可以直接查找到他要占用到哪一个时间。 用了并查集优化后,时间为47MS。
---------------------
作者:shuangde800
来源:CSDN
原文:https://blog.csdn.net/shuangde800/article/details/8022068
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=4e5+5; int n; //vector<int>v[N]; int vis[N]; struct node { int p,d; }a[N]; bool cmp(node x,node y) { return x.p>y.p || x.p==y.p&&x.d>y.d; } int main() { while(cin>>n) { for(int i=1;i<=10005;i++) vis[i]=0; int maxT=0; for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].p,&a[i].d); if(maxT<a[i].d) maxT=a[i].d; } sort(a+1,a+1+n,cmp); int ans=0; for(int i=1;i<=n;i++) { if(!vis[a[i].d ]) { vis[a[i].d ]=1; ans+=a[i].p; } else{ for(int j=a[i].d; j>=1;j--) { if(!vis[j]) { vis[j]=1; ans+=a[i].p; break; } } } } cout<<ans<<endl; } }
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=4e5+5; int n; int f[N]; struct node { int p,d; }a[N]; bool cmp(node x,node y) { return x.p>y.p; } int getf(int x) { if(x!=f[x]) { f[x]=getf(f[x]); } return f[x]; } int main() { while(cin>>n) { for(int i=1;i<=10005;i++) f[i]=i; int maxT=0; for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].p,&a[i].d); if(maxT<a[i].d) maxT=a[i].d; } sort(a+1,a+1+n,cmp); int ans=0; for(int i=1;i<=n;i++) { int fa=getf(a[i].d); if(fa>0) { ans+=a[i].p; f[fa]=fa-1; } } cout<<ans<<endl; } }