zoukankan      html  css  js  c++  java
  • 洛谷P3959 宝藏(状压dp)

    传送门

    为什么感觉状压dp都好玄学……FlashHu大佬太强啦……

    设$f_{i,j}$表示当前选的点集为$i$,下一次要加入的点集为$j$时,新加入的点和原有的点之间的最小边权。具体的转移可以枚举$i$,然后枚举$i$的补集$j$,找出$j$的$lowbit_j$

    那么转移就是$$f_{i,j}=min{f_{i,j-lowbit_j}+min{dis[lowbit_j][i]}}$$

    据说这一部分的复杂度是$O(3^nn)$,因为$n$元素的所有子集的大小之和是$3^n$(然而我并不会证)

    然后考虑把整张图给分层,设$g_{l,i}$表示总层数为$l$,已选点集为$i$时的最小答案,然后转移就是

    $$g_{l,i}=sum_{jin i}g_{l-1,i-j}+l*f_{i-j,j}$$

    据说这个复杂度也是$O(3^nn)$,最后$max{g_{l,2^n-1}}$就是答案了

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     6 char buf[1<<21],*p1=buf,*p2=buf;
     7 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 const int N=13,M=4096,inf=0x01010101;
    19 int a[N][N],f[M][M],g[N][M],ne[M],lg[M];
    20 int n,m,S,s,l,x,y,v;
    21 int main(){
    22 //    freopen("testdata.in","r",stdin);
    23     memset(a,1,sizeof(a));
    24     memset(g,63,sizeof(g));
    25     n=read(),m=read();
    26     S=(1<<n)-1;
    27     for(int i=0;i<n;++i) lg[1<<i]=i;
    28     while(m--){
    29         x=read(),y=read(),v=read();
    30         if(a[--x][--y]>v) a[x][y]=a[y][x]=v;
    31     }
    32     for(int i=1;i<=S;++i){
    33         v=0;
    34         for(int j=s=S^i;j;j=(j-1)&s)
    35         ne[j]=v,v=j;
    36         //枚举i的补集,同时为了保证转移正确性要反着转移才行 
    37         for(int j=v;j;j=ne[j]){
    38             x=lg[j&-j],v=inf;
    39             for(y=0;y<n;++y)
    40             if(1<<y&i) cmin(v,a[x][y]);
    41             f[i][j]=f[i][j^(j&-j)]+v;
    42         }
    43     }
    44     for(int i=1;i<=S;i<<=1) g[0][i]=0;
    45     for(int l=1;l<n;++l)
    46     for(int i=1;i<=S;++i)
    47     for(int j=i;j;j=(j-1)&i)
    48     cmin(g[l][i],g[l-1][i^j]+f[i^j][j]*l);
    49     int v=0x3f3f3f3f;
    50     for(int l=0;l<=n;++l) cmin(v,g[l][S]);
    51     printf("%d
    ",v);
    52     return 0;
    53 }
  • 相关阅读:
    离线安装 Cloudera Manager 5 和 CDH5.10
    Sersync+Rsync实现触发式文件同步
    Azkaban3.x集群部署(multiple executor mode)
    内置函数
    递归
    嵌套函数,匿名函数,高阶函数
    局部变量,全局变量,作用域
    函数的介绍
    文件处理
    第二模块-三元运算
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9683401.html
Copyright © 2011-2022 走看看