HDU-4568 TSP +最短

質問が意図される:n行m列の行列に、数字は(すべての価格を支払うために時間が経過していることに留意)後の行列のコストを表し、行列いくつかの宝物があり、行列ハンターは、すべての宝物を完成取るために任意の境界から行くことができますこれは、任意の境界から出てきました。

解決法:宝13以下の数を確認し、なければなりません、TSPを考えるのは簡単でなければなりません。したがって、我々は最短治療+ DP圧縮された状態のソリューションを使用しています。Sと宝物まず、この全体マップへのすべての事前の宝最短地点のは、準備DPの価格に従うことで、その後、圧力DP、DPの設計DPステータス[S] [今]代表者を好きに始めたとの点セットに行ってきましたです今今宝の最小点で、検索のメモリを転送することができます。

コードの詳細を参照してください、理解して非常に良いことがあります:

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
CONSTの INT N = 210 const  int型 INF = 0x3f3f3f3f CONSTの INT DX [] = { - 1010 }。
const  int型 DY [] = { 010、 - 1 }。
INTの N、M、K、[N] [N]、DP [ 1 << 15 ] [ 15 ]、ES [N]、PX [N]、PY [N]。

構造体DAT {
     int型、D、X、Y。
    BOOL 演算子 <(CONST DAT&RHS)のconst {
         戻り D> rhs.d。
    } 
}。
PRIORITY_QUEUE <DAT> Q;
INT DIS [ 15 ] [N] [N]。
BOOL VIS [N] [N]。
ボイドダイクストラ(int型K){ 
    memsetの(DIS [k]は、0x3fをはsizeof (DIS [K]))。
    memsetの(VIS、0はsizeof (VIS))。
    q.push((DAT){ 0 、PX [K]、PY [K]})。
    DIS [K] [PX [K] [PY [K] = 0 ;
    しばらく(!q.empty()){ 
        DAT U = q.top()。q.pop();
        もし(VIS [UX] [UY])続けます
        VIS [UX] [UY] = 1 以下のためにint型 i = 0 ; iは< 4 ; I ++ ){
             int型 TX = u.x + DX [i]は、TY = u.y + DYの[I]。
            もし(TX < 1 || TX> N || TY < 1 || TY> M || [TX] [TY] == - 1続けますもし(DIS [K] [TX] [TY]> DIS [K] [UX] [UY] + [TX] [TY]){ 
                DIS [K] [TX] [TY]= DIS [K] [UX] [UY] + [TX] [TY]。
                q.push((DAT){DIS [K] [TX] [TY]、TX、TY})。
            } 
        } 
    } 
} 

int型 lowbit(INT X){ int型 RET = 0(; X; X - = X&-x)RET ++。リターンRET; } 

INT DFS(INT今、INT X){
     場合(!DP [今] [X] = - 1戻りDP [今] [X]。
    もし(lowbit(今)== 1戻り ES [X] + [PX [X] [PYの[X]]。
    DP [今] [X] = INF。
    int型 i = 1 ; iが= Kを<; I ++の場合(!(I = X)&&(現・(1 << I- 1 ))){
             int型 TMP = DFS(今^(1 << X- 1)、I)+ DIS [I] [PX [X] [PYの[X]]。
            DP [今] [X] = 分(DP [今] [x]は、TMP)。
    } 
    戻り[今] DPを[X]。    
} 

int型のmain()
{ 
    int型の T。CIN >> T;
    一方、(T-- ){ 
        scanf関数(" %d個の%のD "、&​​N、&M)。
        以下のためのintです i = 1 ; iが<= N; I ++)のためのINT J = 1 ; J <= Mであり、j ++)のscanf(" %dの"、および[I] [J])。
        scanf関数(" %のD "、&K)。
        以下のためにint型私= 1 ; iが= Kを<; Iは++ ){ 
            scanf関数(" %D%dの"、&​​PX [i]は、&PY [I])。
            PX [I] ++; PY [I] ++ ; 
            ダイクストラ(I); 
            ES [I] = INF。
            以下のためのint型 J =1 ; J <= N; J ++)ES [I] =分(ES [i]は、分(DIS [I] [J] [ 1 ]、DIS [I] [J] [M]))。
            INT J = 1 ; J <= Mであり、j ++)ES [I] =分(ES [i]は、分(DIS [I] [ 1 ] [j]は、DIS [I] [N] [J]) ); 
        } 
        のmemset(DP、 - 1はsizeof (DP))。
        int型 ANS = INF。
        以下のためにint型 i = 1 ; iは= Kを<; iは++)ANS =分(ANS、DFS((1 << k)を- 1、I)+ ES [I])。
        もし(ANS == INF)のprintf(" -1 "); のprintf(" %Dを\ n " 、ANS)。
    } 
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/clno1/p/10934224.html