物流・輸送トランス「ZJOI2006」

説明[タイトル]
物流会社はドックから出荷を取る\(\)ドックに搬送\(B \) 超える商品として、我々はする必要があります\(N \)操作を完了する日。一般的には、商品の輸送には、いくつかの駐車桟橋をオンにします。物流会社は、多くの場合、全体の輸送プロセスの厳格な管理と追跡の実施のための一定の輸送ルートを設計します。様々な要因のために、時には桟橋は、貨物をロードおよびアンロードしないであろう。今回は品物が時間通りに目的地に到達できるように、輸送ルートを変更する必要があります。しかし、改訂されたルートは非常に面倒なことで、追加コストをもたらすでしょう。そのため、物流会社が設定したいと考えている\(N \) 輸送計画の日数をするように、できるだけ低い総コスト。

[入力形式
最初の行4つの整数\(N(1 \当量のn \の当量100)、M(1 \当量のm個の\当量20)、K \) と\(E \) \(N- \)貨物の輸送のために必要な日数を表し、\(m個\)は合計桟橋を表し、\(K \)は、輸送ルートごとに必要な変更のコストを表します。次に、\(E \)線がそれぞれの経路は、それぞれ、二つの端子と配線長との間の経路の数のため、三つの整数を含む、記載されている((> 0)\)\前記ハーバー\(A \)の番号(1 \)\、端末\(B \)\(Mを\) 単位長さあたりの交通費\(1 \) 両方向のルート。次の行は、整数である\(D \)の後ろに、\(D \)線各3の整数である\(P(1 <P < M)、B(1 \が\の当量bをLEQ \ N-1当量)\) その数が\(P \)から埠頭\(A \)日に\(B \)デイは(頭と尾を含む)貨物をロードおよびアンロードすることはできません。マリーナでは、おそらく複数の期間には使用できません。しかしながら、任意の時間は、少なくともドックからのものがある\(\)端子に\(Bの\)輸送ルート。

[]出力形式は、
最小の総コストを表す整数を含みます。日路長= N + K *及び輸送ルート変更の輸率の総コスト。

[問題]解決は
容易にこの問題DPことが見られます。
セット(\ [I] F)\前方の代表\(私は\)最小コスト日。列挙\(J \)はセクション表す\(J \)日プログラムの変更を、ある\(F [I] =分 (F [J] + K +コスト(J + 1、I)*(IJ)) \)、\ (コスト(I、J)は\)を表す\(IJを\)可能な限り最良の解決策で一日を過ごすに起因する日。
\(費用(i、j)が \) 最短経路を決定することが可能です。各列挙制限、ドックなら\(K \)日付及び使用することはできません\(IJ \)が交差フラグがピアとして使用することができない(\(VIS [k]は\)に設定されている\します(1 \) )。その後、最短毎に算出に使用することができます\(コスト(I、J)を\)
注意([0] \ F)\転送する場合追加しない\を(K \)

[コード]

#include <iostream>
#include <cstdio>
#include <queue>
#define re register
using namespace std;
typedef long long ll;

ll n, m, kk, e, d;
ll head[10007], pre[20007], to[20007], dis[20007], len, ans[20007];
ll cost[103][103], p[100007], a[100007], b[100007], dp[100007];
bool vis[10007];

ll read() {
    ll ret = 0;
    char ch = getchar();
    while (ch > '9' || ch < '0') {
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ret = ret * 10 + ch - '0';
        ch = getchar();
    }
    return ret;
}

void insert(ll u, ll v, ll w) {
    len++;
    to[len] = v, pre[len] = head[u], dis[len] = w, head[u] = len;
}

void dijkstra() {
    priority_queue< pair<ll, ll> > q;
    q.push(make_pair(0, 1));
    ans[1] = 0;
    while (!q.empty()) {
        ll c = q.top().second;
        q.pop();
        if (vis[c]) continue;
        vis[c] = true;
        for (re ll i = head[c]; i != 0; i = pre[i]) {
            if (ans[c] + dis[i] < ans[to[i]]) {
                ans[to[i]] = ans[c] + dis[i];
                q.push(make_pair(-ans[to[i]], to[i]));
            }
        }
    }
}

int main() {
    n = read(), m = read(), kk = read(), e = read();
    for (ll i = 1; i <= e; i++) {
        ll u, v, w;
        u = read(), v = read(), w = read();
        insert(u, v, w);
        insert(v, u, w);
    }
    d = read();
    for (ll i = 1; i <= d; i++) {
        p[i] = read(), a[i] = read(), b[i] = read();
    }
    for (ll i = 1; i <= n; i++) for (ll j = i; j <= n; j++) {
        for (ll k = 1; k <= m; k++) vis[k] = 0;
        for (ll k = 1; k <= m; k++) ans[k] = 0x7fffffff;
        for (ll k = 1; k <= d; k++) if ((a[k] >= i && a[k] <= j) || (b[k] >= i && b[k] <= j) || (a[k] <= i && b[k] >= j)) vis[p[k]] = 1;
        dijkstra();
        cost[i][j] = ans[m];
        //cout << i << " " << j << ": " <<cost[i][j] << endl;
    }
    for (ll i = 1; i <= n; i++) {
        dp[i] = 0x7fffffff;
        for (ll j = 0; j < i; j++) {
            if (cost[j + 1][i] == 0x7fffffff) continue;
            if (j != 0) dp[i] = min(dp[j] + cost[j + 1][i] * (i - j) + kk, dp[i]); 
            else dp[i] = min(dp[j] + cost[j + 1][i] * (i - j), dp[i]); 
        }
    }
    printf("%lld\n", dp[n]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ak-dream/p/AK_DREAM5.html