トレーニング4 - タイトル
スーパーマーケットは、販売上の製品のセット製品版を持っています。これは、販売が始まる瞬間から始まる時間単位の整数として測定された期限dxだけ販売された各製品x∈Prodの利益PXを稼いでいます。各製品は、販売されるため、正確に時間の1つの単位を取ります。販売スケジュールは、製品の注文サブセットは≤売るの順序に従って、各製品の販売x∈Sellは、完了期限DX前または単にDXの有効期限が切れるよう製品版を販売です。販売スケジュールの利益は、利益(売る)=Σである
x∈Sellpx。最適な販売スケジュールは、最大の利益を持つ予定です。
例えば、製品を考えるのProd = {A、B、C、D}(PA、DA)と=(50,2)、(PB、DB)=(10,1)、(PC、DC)=(20 、2)、及び(PD、DD)=(30,1)。可能販売スケジュールは、例えば表1に記載されている、スケジュール売り= {D}示すこと時間0および時間1における両端の製品Dの開始の販売、しばらく時間1での製品の販売が開始されると時間2.これらの製品のそれぞれの両端には、その期日までに販売されています。販売は、最適なスケジュールであり、その利益は80です。
入力テキストファイルから製品のセットを読み取り、製品の各セットに最適な販売スケジュールの利益を計算するプログラムを作成。
入力
製品のセット整数の集合における製品の数である整数0 <= N <= 10000で始まり、そしてに続くN個の対PIジ、1 <= PI <= 10000および1 <=ジ<=利益とi番目の製品の販売期限を指定10000、。ホワイトスペースは、入力中に自由に発生する可能性があります。入力データは、ファイルの終わりで終了し、正しいことが保証されています。
出力
製品の各セットのために、プログラムは標準出力にセットに最適な販売スケジュールの利益を印刷します。それぞれの結果は、別の行の先頭から印刷されます。
サンプル入力
4 50 2 10 1 20 2 30 1
7 20 1 2 1 10 3 100 2 8 2
5 20 50 10
サンプル出力
80
185
ヒント
サンプル入力は、2つの製品のセットが含まれています。最初のセットは、第二のセットは、7つの製品のためのものである、表1からの産物をコードします。これらの製品の最適なスケジュールの利益は185です。
方法1:
#pragma warning (disable:4996)
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#define inf 0X7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e4 + 10;
struct Good
{
int p;
int d;
};
priority_queue<Good> q;
bool operator<(Good x, Good y)
{
return x.p > y.p;
}
Good s[maxn];
bool cmp(Good x, Good y)
{
return x.d < y.d;
}
int n, ans;
int main()
{
while (scanf("%d", &n) != EOF)
{
ans = 0;
for (int i = 1; i <= n; i++)
scanf("%d%d", &s[i].p, &s[i].d);
sort(s + 1, s + n + 1, cmp);
for (int i = 1; i <= n; i++)
if (q.size() == s[i].d)
{
if (q.empty() || s[i].p > q.top().p)
{
q.pop();
q.push(s[i]);
}
}
else if (q.size() < s[i].d)
q.push(s[i]);
while (!q.empty())
{
ans += q.top().p;
q.pop();
}
printf("%d\n", ans);
}
return 0;
}
アイデア:
貪欲は、毎日は現在、商品を販売する最も収益性の高いを販売します。
ヒープのトップを維持しながら、アレイに有効期限に応じて、小から大順に商品は、最大の利益商品バイナリヒープです。
配列を通る時間が満了していない場合、あなたはスタックに商品を販売することができます。現在の時刻は商品を満了した場合、(その時は販売することができる前に商品がスタック内にあるので)、最も収益性の高い商品を交換する前に。
このように、商品のバイナリヒープ残りは販売商品の機能です。
方法2:
#pragma warning (disable:4996)
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define inf 0X3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e4 + 5;
int fa[maxn];//天数
void initial(int n)
{
for (int i = 1; i <= n; i++)
{
fa[i] = i;
}
}
int get(int x)
{
if (x == fa[x])
return x;
return fa[x] = get(fa[x]);
}
void merge(int x, int y)
{
fa[get(x)] = get(y);
}
struct Good
{
int p;
int d;
};
Good s[maxn];
bool cmp(Good x, Good y)
{
return x.p > y.p;
}
int n, ans;
bool v[maxn];
int main()
{
while (scanf("%d", &n) != EOF)
{
ans = 0;
int day = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &s[i].p, &s[i].d);
day = max(day, s[i].d);
}
sort(s + 1, s + n + 1, cmp);
initial(day);
for (int i = 1; i <= n; i++)
{
int t = get(s[i].d);
if (t > 0)
{
ans += s[i].p;
fa[t] = get(t - 1);
}
}
printf("%d\n", ans);
}
return 0;
}
アイデア:
貪欲、優先度が最も大きい商品の利益を販売し、最新の時間を販売する、最終的に最大の利益を得ることができるようになります。
日数を維持するために、互いに素セットで、我々は1コレクション内の商品に連続した時間を売却する必要があります。このように、すべての時間とは、最新のタイムチェック売れ残り品を見つけるために設定することができます。