n個の項目がありますが、最初のiのアイテムとしてマークされ、\((D_I、P_I)\) 、を示している商品棚の生活\(D_I \)日の値\(P_I \) 、今最初の日から、唯一の日商品を販売し、収益を最大化、\(N- \のLeq 10000 \) 。
ソリューション
これは整然とした列に、明確コレクションの対象であり、無秩序、その後、最初の並べ替えを検討します
方法1:プレス\(P_Iの\)降順
シリーズは、スキャンから行った後、最初の最大の項目の値を知るのは簡単、商品を選択することを教えてくれるシンプルなアイデアが、最善は尽くしますか?一部の商品は、特定のケースの前面に配置することができ、問題の観点からの回答は、毎日がボックスであることを想像し、各アイテムはボールです。
最後のシナリオでは、ボックスは、他のボール明らかに低値ながらあなたは、他のボールにボックスを解放するのに代わって、ボールを選択しない場合は、すぐに戻って質問に、いずれかを取り戻すことができないボールの中に配置する必要があります、その結果は確かに優秀ではありません。
質問は今、ボールは一日に配置する必要が明らかに?我々は日数後の日にあなたがいるため2日間、によって可能な限りで置くことができなければならないシンプルなアイデア\(X、Y、X < Yの\) 、箱の裏だけ三つの可能性、\(X-、 Yの\)を選択することができる、\(X- \)は、選択することができる\(Y軸\)を選択することができない、\(X軸、Y軸\)は、いずれの場合も選択することができ、結果が最良でなければなりません。
だから我々は単に選挙を持つように選択することができ、およびにより、可能な限りの選挙には数日後に、最適化するために、前後にスキャンし、\を(O(N ^ 2) \) スキャン、ツリーラインを使用しますが、良いことができませんあなたはそれがかどうかを選択できるかどうかを確認する必要がある場合、我々は一日は、商品を販売することを選択した場合には、バランスの取れた木、毎日の番号が追加されたツリーを使用したい場合があり、書き込み、それは限り、ツリー内の日数の対応する番号を削除しますバランスのとれたツリーに対応する最初のルックの貯蔵寿命は、以下の時間複雑度に等しいとすることができる(O(nlog(N))\)\、定数が比較的低いの方法としては、大きすぎます。
参照コード:
#include <iostream>
#include <cstdio>
#include <set>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define Size 15000
using namespace std;
struct item{
int p,d;
il bool operator<(const item&x)const{
return p>x.p;
}
}I[Size];
set<int>S;
set<int>::iterator m;
il void read(int&);
int main(){int n;
while(scanf("%d",&n)!=EOF){int ans(0);S.clear();
for(int i(1);i<=10000;++i)S.insert(i);
for(int i(1);i<=n;++i)read(I[i].p),read(I[i].d);
sort(I+1,I+n+1);
for(int i(1);i<=n;++i){
m=S.upper_bound(I[i].d);
if(m==S.begin())continue;
S.erase(--m),ans+=I[i].p;
}printf("%d\n",ans);
}
return 0;
}
il void read(int &x){
x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
アクトII:プレス\(D_I \)
シリーズは、スキャンから行った後に1が貪欲最適引数であれば、あなただけ(つまり、最悪の候補が選択されているに最高で選択された候補者が、そのようなkrucalアルゴリズムとして、選択することが可能である)、これはアイテムの最短貯蔵寿命であることを知っています、その後、第二は貪欲別の方法で、単に、それが始まりですが、必ずしも最適ではない意思決定を行うことが、後に結果が最適になるように、最悪のソリューションを交換していきます。
小さなヒープルートを維持したい場合があり、ソートキーワード\(D_I \) 、アイテムの貯蔵寿命は、ヒープ内の要素の数よりも大きい場合、明らかヒープは、常に商品の賞味期限内の要素の現在の数よりも少ない、シーケンスをスキャン前後をヒープ、またはそうでなければ、比較的一定の小さな行うことができますので、ヒープのトップである、明らかに商品の最悪を置き換えるために、商品を交換する必要があります入会(\ O(nlog(N-)))\を(使用する方法を)数日のためにこの条件に、私たちはしおれ。
ところで、なぜ押さないでください\(D_I \)の並べ替えではありませんか?代替欲が前提があるので、あなたは押さない場合は、交換することができなければならない(D_I \)\ソートを将来的に交換することはできませんあなたが一日だけの貯蔵寿命を有する例を置き換えるためにあなたを導く、あなたがでも交換日の貯蔵寿命の数十を持っていますが、商品の後。
参照コード:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define il inline
#define ri register
#define Size 10500
#define swap(x,y) x^=y^=x^=y
using namespace std;
struct big{
int a[Size],n;
il void push(int x){
a[++n]=x;int p(n);
while(p>1)
if(a[p>>1]>a[p])
swap(a[p>>1],a[p]),
p>>=1;
else break;
}
il void pop(){
swap(a[1],a[n]),--n;
int p(1),s(p<<1);
while(s<=n){
if(s<n&&a[s+1]<a[s])++s;
if(a[s]<a[p])swap(a[s],a[p]),
p=s,s=p<<1;
else break;
}
}
}B;
struct pi{int p,d;
il bool operator<(const pi&x)const{
return d<x.d;
}
}p[Size];
il void read(int&);
int main(){int n;
while(scanf("%d",&n)!=EOF){
for(int i(1);i<=n;++i)
read(p[i].p),read(p[i].d);
sort(p+1,p+n+1);
for(int i(1);i<=n;++i){
if(p[i].d>B.n)B.push(p[i].p);
else if(B.a[1]<p[i].p)
B.pop(),B.push(p[i].p);
}int ans(0);
for(int i(1);i<=B.n;++i)
ans+=B.a[i];printf("%d\n",ans),B.n=0;
}
return 0;
}
il void read(int &x){
x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}