実行HDU 6071レイジー(最短)

トピックリンク

http://acm.hdu.edu.cn/showproblem.php?pid=6071

問題の解決策

それは、信頼IQ問題の乱用です。

まず、二次疑問があり、この質問は、この問題が発生した後の波に変換されます。与えられた\(A_1、A_2、...、 A_N \) と\(K \) 作り求めて\(\合計^ { N} _ {i = 1} a_ix_i = B \) 正の整数解と\(B \ GE K \)最小\(B \)の値。この問題では\(N- = 4、a_iを\ル30000、K \ル10 ^ {18} \)
これは、最短古典的な問題のようですが、私は3時間の練習を考えていなかったと思います......
おそらく見つけます\(a_k \) ほぼ一定の最小を見つけるセーブ)とダイに\(\ a_k)ビルドの残り数システムの各点について、各番号\(Tは\)\((T + a_iを)\ MOD a_k(K = 1,2、... 、N)\) 接続されたエッジ、そのよう\(1 \)(J \)\最短モードである\(a_k \) I \(J \)の最小\(Bの\) これはあってもよい\(O(na_i \ログn )\) 上記課題を解決するための時間の期間内に。
のは、この問題を入れてみましょう(\ \ {a_iを\} = \ {D_I \}、K = X \) と呼ば回答\(F(X)\)

そして、上記のような問題点、異なる問題や方法私の解決策を転換にどのように元の問題を検討してください。
ここに私の方法は、(ああを歓迎質問があり、私はそれが問題に欠けていると思うが、この問題は確かに非常に弱いデータである)である:
セット\(D_1、D_2、D_3、 D_4 \) されている\(1,2,3,4- \)ポイントの数にもすぐ隣側が、我々がします(2 \)\バックに出発点を\(2 \)の5つのポイントに分けパス:

(1)から(\ 2 \)する\(1 \) その後、バック長さ\(2d_1 \)

(2)から\(2 \)(3 \)を\、長さ戻ってくる\(2d_2 \)

(3)から\(2 \)(3 \)を\次いで及び\(4 \) \(1 \)以下\(1 \)当時、そして。
この時点で\(D_2 \)だけ各ラウンドの後側回、\(D_3 \)少なくとも一回前後縁(の出現妨げることなく\(D_3を\)に直接\(D_4は\)法律判例はない)、\ (D_4 \ )側と任意の回数、長から\(2d_2 2k_3d_3 + + + 2d_3 2k_4d_4 \) \(K_3、K_4 \)は、任意の正の整数です)

(4)から\(2 \)(1 \)を\次いで及び\(4 \) \(3 \)以下\(3 \)当時、そして。前の場合と対称、長さ\(2d_1 2k_3d_3 + + + 2d_4 2k_4d_4 \) \(K_3、K_4 \)非負整数)

リングは、任意の回数およびから追加することができるが(5)、リングを取ります。長さ\(D_1 D_3 + + + D_2 k_1d_1 D_4 + + + k_2d_2 k_4d_4 k_3d_3 + \) \(K_1、K_2、K_3、K_4 \)非負整数)
次に上記の議論を単純化する検討:(3)及び(4)それぞれが一度や二度行ってください(5)に相当(5)を行う(それは、複数のと同等であるため、複数の同等作る\(K)\付加価値)、それはと考えられているが(5)まで再びそれを行います。
(1)(5)、(2)(5)を同時に意味を成していない場合は、(1)(3)、(2)(4)(5)は意味をなさないことと同等のものをやっている間。
最適な戦略を考えてみます。

(1)〜(5)を1回行うようにすれば、(3)及び理由(3)(4)、実行する必要がない、(4)動作中(5)と等価である\(K \)を加えた値。したがって、答えのこの部分がされて\(F(N - D_1-D_2-D_3-D_4)D_1 + + + D_2 D_3 D_4 + \)

(2)(5)でない場合、次いで、(3)及び(4)であってもよい。このセクションへの1つの答えである(\ \分(F(N + 2d_4 -2d_1-2d_4)+ 2d_1、F(N- 2d_2-2d_3)+ 2d_2 + 2d_3)\)

(3)(3)(4)(5)、次いで(1)を考慮せず、(2)、このセクションでは、上述の問題に等しくなければならない場合\(N = 2、A_1 = D_1、A_2 = D_2、K = N \)答えたとき。
時間複雑\(O(D \ dはログ)\) さらに詳しい詳細\(ShortestPath(N-、4N)+ ShortestPath(N-、2N)\)
執筆のこの種の唯一の利点は、一定の小さなバーであることが... ...

次の練習問題のソリューションである
ため、残りの行のモジュラス(\ \分(D_1、D_2)\) 次に設定([I] [J fを\を ] \) を表し\を(私は\)この時点で、残りはあります\(J \)の回答、及び最短DP転送要求たいです。
時間複雑\(O(D \ログD)\) さらに詳しい詳細\(ShortestPath(4N、8N)\)

コード

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define llong long long
using namespace std;

void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

const int N = 6e4;
const int M = 1.2e5;
const llong INF = 1000000000000200000ll;
struct Edge
{
    int v,nxt; llong w;
} e[(M<<1)+3];
int fe[N+3];
struct DijNode
{
    int u; llong x;
    DijNode() {}
    DijNode(int _u,llong _x) {u = _u,x = _x;}
    bool operator <(const DijNode &arg) const {return x>arg.x;}
};
priority_queue<DijNode> pq;
llong dis[N+3];
bool vis[N+3];
llong d[5],x;
int n,en;

void addedge(int u,int v,llong w)
{
    en++; e[en].v = v; e[en].w = w;
    e[en].nxt = fe[u]; fe[u] = en;
}

void Dijkstra()
{
    memset(dis,30,sizeof(dis)); memset(vis,0,sizeof(vis));
    dis[0] = 0ll; pq.push(DijNode(0,0ll));
    while(!pq.empty())
    {
        DijNode tmp = pq.top(); pq.pop(); int u = tmp.u;
        if(tmp.x!=dis[u]) continue;
        if(vis[u]) continue;
        vis[u] = true;
        for(int i=fe[u]; i; i=e[i].nxt)
        {
            int v = e[i].v;
            if(dis[v]>dis[u]+e[i].w && vis[v]==false)
            {
                dis[v] = dis[u]+e[i].w;
                pq.push(DijNode(v,dis[v]));
            }
        }
    }
}

void clear()
{
    for(int i=0; i<=en; i++) e[i].v = e[i].w = e[i].nxt = 0;
    for(int i=0; i<=n; i++) fe[i] = 0;
    en = n = 0;
}

llong solve(llong x)
{
    if(x<0) return 0ll;
    llong ret = x;
    while(dis[ret%n]>ret) ret++;
    return ret;
}

int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld%lld",&x,&d[1],&d[2],&d[3],&d[4]);
        llong ans = INF,tmp;
        n = min(min(d[1]+d[1],d[2]+d[2]),min(d[3]+d[3],d[4]+d[4]));
        for(int i=0; i<n; i++)
        {
            for(int j=1; j<=4; j++)
            {
                addedge(i,(i+d[j]+d[j]-1)%n+1,d[j]+d[j]);
            }
        }
        Dijkstra();
        tmp = solve(x-d[1]-d[2]-d[3]-d[4])+d[1]+d[2]+d[3]+d[4]; ans = min(ans,tmp);
        tmp = solve(x-d[1]-d[1]-d[4]-d[4])+d[1]+d[1]+d[4]+d[4]; ans = min(ans,tmp);
        tmp = solve(x-d[2]-d[2]-d[3]-d[3])+d[2]+d[2]+d[3]+d[3]; ans = min(ans,tmp);
        clear();
        n = min(d[1]+d[1],d[2]+d[2]);
        for(int i=0; i<n; i++)
        {
            for(int j=1; j<=2; j++)
            {
                addedge(i,(i+d[j]+d[j]-1)%n+1,d[j]+d[j]);
            }
        }
        Dijkstra();
        tmp = solve(x); ans = min(ans,tmp);
        clear();
        printf("%lld\n",ans);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/suncongbo/p/11360830.html