• $[NOIp2017]$ 宝藏 状压$dp$


    (Sol)

    觉得这里是个很巧妙的地方吖,就是记下当前扩展点集的最大深度,然后强制下一步扩展的点集都是最大深度+1.这样做在当前看可能会导致误算答案导致答案偏大,但是整个(dp)完成后一定可以得到最优解.

    怎么计算扩展点集的代价呢,显然是要扩展的点向已扩展的点里连最短边,这个可以暴力计算.

    注意一个细节就是输入可能有重复的边,取边权最小的即可.图论题都要注意这一点!

    (Code)

    #include<bits/stdc++.h>
    #define il inline
    #define Ri register int
    #define go(i,a,b) for(Ri i=a;i<=b;++i)
    #define yes(i,a,b) for(Ri i=a;i>=b;--i)
    #define e(i,u) for(Ri i=b[u];i;i=a[i].nt)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define int long long
    #define db double
    #define inf 2147400000
    using namespace std;
    il int read()
    {
        Ri x=0,y=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        return x*y;
    }
    const int N=13,M=1005;
    int n,m,S,as,dis[N][N],a[1<<N],f[N][1<<N];
    il int lowbit(Ri x){return x&(-x);}
    il int cal(Ri i,Ri j)
    {
        Ri ret=0,i1,j1,tmp=j,cur;
        while(i)
        {
    	    i1=lowbit(i),j=tmp,cur=inf;i^=i1;
    	    while(j)j1=lowbit(j),j^=j1,cur=min(cur,dis[a[i1]][a[j1]]);
    	    ret+=cur;
        }
        return ret;
    }
    signed main()
    {
        n=read(),m=read(),S=(1<<n)-1;
        mem(dis,127);mem(f,127);
        go(i,0,n-1)f[1][1<<i]=0,a[1<<i]=i;
        go(i,1,m){Ri u=read()-1,v=read()-1;dis[u][v]=dis[v][u]=min(dis[u][v],read());}
        go(i,1,S)
        {
    	    Ri j=(i-1)&i;
    	    while(j)
    	    {
    	        Ri k=i^j,sum=cal(k,j);
    	        go(dep,2,n)f[dep][i]=min(f[dep][i],f[dep-1][j]+sum*(dep-1));
    	        j=(j-1)&i;
    	    }
        }
        as=f[1][S];go(i,2,n)as=min(as,f[i][S]);
        printf("%lld
    ",as);
        return 0;
    }
    
    
  • 相关阅读:
    内部类,匿名内部类?
    抽象和接口的区别?
    多态的好处?
    怎么防止重复提交?
    java网络编程第二章
    java网络编程第一章
    多态的好处
    静态变量与实例变量(方法)的区别
    杨辉三角
    鸿蒙系统之内核层
  • 原文地址:https://www.cnblogs.com/forward777/p/11735624.html
Copyright © 2020-2023  润新知