bzoj 3055礼物运送 floyed + 状压DP

bzoj 3055: 礼物运送

floyed first 设f[i][S]表示取到了S集合中的所有点(不一定是经过的所有点),最后停在了i的最优值。

初始就f[i][{i}] = dis[1][i]

状态转移直接转就好了

f[i][S] + dis[i][j] -> f[j][S + {j}]其中 i 属于 S,1 <= j <= n

设tim[S] = min{f[i][S]}

答案就取到

           ans = min{max{tim[S],tim[Cs]}}

 1 #include <map>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <climits>
 6 #include <algorithm>
 7 using namespace std;
 8 inline void read(int &x){
 9     x=0;char ch;bool flag = false;
10     while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
11     while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
12 }
13 inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
14 inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
15 inline int cat_abs(const int &x){return x < 0 ? -x : x;}
16 const int maxn = 19;
17 const int maxs = (1<<19) + 1;
18 int dis[maxn][maxn],n,f[maxn][maxs],tim[maxs];
19 inline void init(){
20     memset(dis,0x3f,sizeof dis);
21     memset(f,0x3f,sizeof f);
22     memset(tim,0x3f,sizeof tim);
23 }
24 void floyed(){
25     for(int i=1;i<=n;++i){
26         dis[i][i] = 0;
27         for(int j=1;j<=n;++j){
28             if(i == j) continue;
29             for(int k=1;k<=n;++k){
30                 dis[i][j] = cat_min(dis[i][j],
31                 dis[i][k] + dis[k][j]);
32             }
33         }
34     }return;
35 }
36 map<int,int>ma;
37 int main(){
38  
39     int m;read(n);read(m);
40     init();
41     for(int i=1,u,v,d;i<=m;++i){
42         read(u);read(v);read(d);
43         if(dis[u][v] > d) dis[u][v] = dis[v][u] = d;
44     }
45     floyed();
46     for(int i=0;i<=18;++i) ma[1<<i] = i+1;
47     for(int i=1;i<=n;++i) f[i][(1<<0) | (1<<(i-1))] = dis[1][i];
48     for(int i=0,x=0;i<(1<<n);x = (++i) ){
49         while(x){
50             int p = ma[x&-x];x -=x&-x;
51             for(int j=1;j<=n;++j){
52                 if( f[j][i | (1<<(j-1))] > f[p][i] + dis[p][j]){
53                     f[j][i | (1<<(j-1))] = f[p][i] + dis[p][j];
54                 }
55             }
56         }
57     }
58     for(int i=0,x=0;i<(1<<n);x = (++i) ){
59         while(x){
60             int p = ma[x & -x];x -= x&-x;
61             tim[i]=cat_min(tim[i],f[p][i]);
62         }
63     }
64     int ans = 0x7f7f7f7f;
65     for(int i=0;i<(1<<n);++i){
66         ans = cat_min(ans,cat_max(tim[i],
67         tim[1 | (( (1 << n)-1 )^i) ]));
68     }printf("%d
",ans);
69     //getchar();getchar();
70     fclose(stdin);fclose(stdout);
71     return 0;
72 }
人就像命运下的蝼蚁,谁也无法操控自己的人生.
原文地址:https://www.cnblogs.com/Skyminer/p/6023156.html