zoukankan      html  css  js  c++  java
  • [NOIP2017] 宝藏 【树形DP】【状压DP】

    题目分析:

    这个做法不是最优的,想找最优解请关闭这篇博客。

    首先容易想到用$f[i][S][j]$表示点$i$为根,考虑$S$这些点,$i$的深度为$j$情况的答案。

    转移如下:

    $f[i][S][j] = min(w(i,k)*(j+1)+f[k][S_0][j+1]+f[i][S-S_0][j])$ 其中$S != {i}$且$S_0 subsetneqq S$且$k in S_0$

    $f[i][S][j] = 0$其中$S={i}$

    这样已经可以通过了,时间复杂度是$O(n^3*3^n)$,原因是冗余状态太多。

    但我们注意到对于每个集合我们都要遍历所有的为根的情况,用$g[i][S][j]$存储集合$S$中为根的最小值,可以优化到$O(n^2*3^n)$。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n,m;
     5 
     6 int g[13][13];
     7 
     8 int f[13][1<<12][13],gi[13][1<<12][13];
     9 
    10 void read(){
    11     scanf("%d%d",&n,&m);
    12     memset(g,0x3f,sizeof(g));
    13     for(int i=1;i<=m;i++){
    14     int x,y,v; scanf("%d%d%d",&x,&y,&v);
    15     if(g[x][y] > v) g[x][y] = g[y][x] = v;
    16     }
    17 }
    18 
    19 void paint(int now,int S,int j){
    20     for(int i=1;i<=n;i++){
    21     if((1<<i-1)&S) continue;
    22     gi[i][S][j] = min(1ll*gi[i][S][j],f[now][S][j]+1ll*g[now][i]*j);
    23     }
    24 }
    25 
    26 void work(){
    27     memset(f,0x3f,sizeof(f));memset(gi,0x3f,sizeof(gi));
    28     for(int i=n-1;i>=0;i--){
    29     for(int j=1;j<=n;j++){
    30         f[j][1<<j-1][i] = 0;
    31         paint(j,1<<j-1,i);
    32     }
    33     for(int S=0;S<(1<<n);S++){
    34         int zeta = __builtin_popcount(S);
    35         if(zeta > n-i || zeta <= 1) continue;
    36         for(int k=1;k<=n;k++){
    37         if(!((1<<k-1)&S)) continue;
    38         for(int S1 = S;S1;S1 = (S1-1)&S){
    39             f[k][S][i] = min(gi[k][S1][i+1]+f[k][S-S1][i],f[k][S][i]);
    40         }
    41         paint(k,S,i);
    42         }
    43     }
    44     }
    45     int ans = 2147483647;
    46     for(int i=1;i<=n;i++){
    47     ans = min(ans,f[i][(1<<n)-1][0]);
    48     }
    49     printf("%d",ans);
    50 }
    51 
    52 int main(){
    53     read();
    54     work();
    55     return 0;
    56 }
  • 相关阅读:
    Java并发编程实战3-可见性与volatile关键字
    Java并发编程实战2-线程安全
    Java词频统计
    Java中split的对象被特殊字符(.或|)分隔
    Kernel Space与User Space(转)
    [Python]Pandas简单入门(转)
    Python的自省机制
    谈谈Python中元类Metaclass(二):ORM实践
    Python的垃圾回收机制
    [Python]Pip换源以及设置代理
  • 原文地址:https://www.cnblogs.com/Menhera/p/9207813.html
Copyright © 2011-2022 走看看