P3620 [APIO / CTSC 2007]データのバックアップ[貪欲プライオリティキュー+]

タイトル説明

あなたは、IT企業は、大規模なオフィスビルやオフィスビルなどのバックアップのためのコンピュータデータの(事務所)です。しかし、データのバックアップは面倒な作業ですので、自宅で座って、コンピュータゲームの楽しさを楽しみながら、あなたは、お互いの間で異なる構築相互バックアップを許可するようにシステムを設計します。

既知のオフィスは同じ通りに位置しています。あなたはペアリングこれらの建物(2グループ)を与えることにしました。それらはケーブルネットワークを敷設これら二つの建物の間を通過できるように、建物のそれぞれは、互いにバックアップすることができます。

しかし、ネットワークケーブルのコストが高いです。ローカル通信会社だけが唯一のオフィス(または2Kオフィスの合計)スケジュールバックアップにKにできることを意味Kケーブルネットワーク、を提供することができます。オフィスビルの任意のペアの固有のセット(つまり、建物の2Kが異なっていなければならない)に属しています。

また、テレコム会社は、ネットワークケーブルの長さ(キロメートル)の電荷が必要でした。したがって、あなたはできるだけ短いケーブルの長さの合計を作るオフィス向けたK選択する必要があります。言い換えれば、あなたは、各オフィスビルの組となるべく小さい(総距離)の間の距離を作り、事務所のKを選択する必要があります。

ここでは一例だ、図に示すように、あなたは、ストリートのオフィスビルの5台のクライアントを、持っていると仮定します。5つの事業所は、ハイストリート1キロ、3キロ、4キロ、6キロと12キロオフィスからの出発点に位置しています。テレコム会社はK = 2本のケーブルを提供します。

IMG

最良の例では、最初のペアリング方式であり、接続された第二の局は、第三及び第四の建物に接続されています。従ってK = 2は、ケーブルの使用を必要とすることができます。第1条のケーブルの長さは3キロ、1キロ= 2キロで、バー2のケーブルの長さは6キロ、4キロ= 2キロです。この方式は、4キロペアネットワークケーブルの全長を必要とし、最小距離要件を満たします。


解決

まず第一に、最適な解決策を考えることは容易では唯一の構築二つの隣接するオフィスビルで2を接続する必要があります。その理由は、任意の二つの隣接するケーブル間彼らの唯一の接続ほど良く、いくつかのないように接続された任意の建物全体でいくつかのケーブルは非常に簡単です。

まあ、我々は唯一の各隣接するオフィスビルとの間の接続ケーブルをどのように扱うかの問題は、すべて2つのオフィスビルの間の距離を分析し、我々は番号が付けられます(SIM-N-1 \ \ 1)\

私はDPを考えることですここです、データ範囲無知な力で直接見ての結果は、\()^ 2 O(N \)つま先が今までありませんでしたいです。次に考えたのは行うことができますネットワークを流れているようだが、また、一見の生活を困難にするの複雑さ。


Qiazhiyisuan老婦人、(ブックLYDに応じて)は、以下の分析を持っていました:

任意のペア(二つの隣接する)の建築用\(I、J \) 局所最適解の2つのだけの状況:

  1. 接続\(I、J \)
  2. 接続\(I-1、Iは\ ) と\(J、J + 1 \)

明らかに、最適な状況1 \は、(i-1、iが\ ) と\(J、J + 1 \は ) 選択されていません。ケース2の場合は、以降のすべての距離が正であるので、選択肢の\(I-1、Iは\ ) と\(J、J + 1 \ ) 一定期間のみ選択よりも優れている定数2。

しかし、我々はその、直接貪欲であれば、これは両側からの最小距離を選択することができない原因になりますが、最適解はそれらの両方を含めることは可能であるとして、あなたは答えに最小累積距離を選択するたびに、後に効果があることがわかりました。

理由はここに起因する直接貪欲遅延作用気づいたことは、現在の状態の両側からの最短距離の選択に影響を与えるため、単純に、ケースであること、そして私たちは考えるかもしれません可能性が戻って、以前に選択の影響排除欲を。


その後、我々は貪欲を取得することができます。リストの確立(。。-n-SIM \ 1 1 \)を\を、すべての距離に対応し、プライオリティキューにマッピングされました。各貪欲最短距離(\いるK_d \)答えに蓄積は、それが想定され、その位置\(D \) \(D-1、D + 1 \) 著しいフラグが選択されない示す2は、リスト削除\を(D-1、D、 D + 1 \) ノード、ヒープを削除するために、対応するノードは、その元の位置にリストに新しいノードを追加し、それらの権利がある\(K_ {D-1} + {D}。1 + K_ -k_ {D} \)(Kは距離の大きさ)だけでなく、新しいスタックの重量で\(K_ {D-1} + K_ {D + 1} -k_ {D } \)ノード。我々は状態の後、再び新しいノードを選択すると、結果として、選択する前に除去されます\(dは\)選択した場合と同じ影響、\(D-1、D + 1 \)の代わりに、選挙の(\ D \) 。


下の図は、黒塗りは、選択されたセグメントを示しています。

第1選択位置\(D \)回答の時点で\(ANS = \ cdotsいるK_d + \)

最初のポイントを選択します

回答の点の第二選択位置\(ANS = \ cdots + K_D + K_ {D-1} + K_ {D + 1} -k_ {D} = \ cdots + K_ {D-1} + K_ { D + 1} \)

第二の点を選択します

私たちは、元のノードを削除し、新しいノード操作は、決定をしたサブの質問に実際に相当し、徐々に大きく問題のある子を解決します。

図の赤枠が最適解の現在の状態を表している場合、実際には、彼が問題にサブ最適解である、意思決定の後、私たちは、その内部に関係なく、直接この問題へのサブ最適なソリューションを使用することができます何を構成しています。


私たちは、次のグローバル最適解でもこの特性を満たすことを証明、全体の問題を解決するために、より一般的なケースを証明する必要があります。

まず第一に、明らかに我々はすべてのサブ問題は、そのサブ課題の全てより少ないが含まれている必要があり、貪欲包括的意思決定している(これは間隔の問題です)。

我々としても摂動法とスケーリング則のスコープを使用しての正しさを証明する貪欲かもしれません。

サブ問題は、次のようにすることを選択領域の正しさは、現在の状態が想定されているマークされていないことを証明しようとします。

すなわち、黒領域としてサブ最適解場合、前のステップ、灰色の領域に、現在の最短距離です。この時点で私たちは灰色の領域を選択した場合は、すべての距離の持っている必要があります\(> \)灰色距離の右端その部分のいずれか、およびすべての黒い部分から選択されています\(<\)ので、灰色の領域からの私たちが選択した後、このサブ問題に灰色の領域は距離よりも小さな灰色の領域を削減する、これは間違いなく、最適な解決策ではない、答え灰色の領域よりも大きい距離に増加しました。

明らかに、このプロパティは任意のサブ問題に拡張することができ、それは貪欲として意思決定を行うために、いつでも、結果を悪化させない、です。


また、我々はいくつかの詳細に注意を払う必要があります:境界処理のリストを、我々は、テーブルのヘッダーとフッターが選択されていないことを確実にしたい(これらは任意のサブ質問に含まれていない)、単に初期値は無限大に割り当てることができます。

他の同様の質問:P1484の木P1792 [ナショナルチーム]木

参照コード

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 500010
#define ll long long
#define INF 0x7fffffff
using namespace std;
inline ll read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct node{
    ll val;
    int id;
    bool operator<(const node &a)const{
        return val>a.val;
    }
    node(){}
    node(int _id,ll _val){id=_id,val=_val;}
};
ll a[N],n,k,sum[N];
bool v[N];
priority_queue<node> q;
struct link{
    ll val;
    int pre,next;
}g[N];
int main()
{
    n=read(),k=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    for(int i=1;i<n;++i){
        g[i].pre=i-1,g[i].next=i+1;
        sum[i]=a[i+1]-a[i];
        g[i].val=sum[i];
        q.push(node(i,sum[i]));
    }
    g[n].val=g[0].val=INF;
    ll ans=0;
    for(int i=1;i<=k;++i){
        while(v[q.top().id]) q.pop();
        node x=q.top();q.pop();ans+=g[x.id].val;
        g[x.id].val=g[g[x.id].next].val+g[g[x.id].pre].val-g[x.id].val;
        v[g[x.id].next]=v[g[x.id].pre]=1;
        q.push(node(x.id,g[x.id].val));
        g[x.id].next=g[g[x.id].next].next;
        g[x.id].pre=g[g[x.id].pre].pre;
        g[g[x.id].pre].next=x.id;
        g[g[x.id].next].pre=x.id;
    }
    printf("%lld\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/DarkValkyrie/p/11499533.html