• 《P3959 [NOIP2017 提高组] 宝藏》


    这题数据量很小,显然是状压和dfs。

    dfs + 剪枝也可以过这题,但是剪枝比较玄学。。

    状压dp:

    f[i]表示选了的点状态为i时的最小总代价。

    dep[i][j]表示选点状态为i的最优状态时的,j的深度。

    因为这题多余的边不用连,显然最终的答案是一棵树。

    每次选定两条边加入即可。注意的是i 向 j转移,那么他的相对最优深度也要全部转移。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e4 + 5;
    const int M = 3e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 0x3f
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
    
    int dis[15][15],f[1 << 12],dep[1 << 12][15],n,m;
    int solve(int x){
        memset(f,INF,sizeof(f));
        memset(dep,INF,sizeof(dep));
        dep[1 << (x - 1)][x] = 1;
        f[1 << (x - 1)] = 0;
        for(int i = 0;i < (1 << n);++i){
            for(int j = 1;j <= n;++j){
                if(((i >> (j - 1)) & 1) == 0) continue;//要满足j在i里面
                for(int k = 1;k <= n;++k){
                    if(((i >> (k - 1)) & 1) == 1) continue;//要满足k不在i里面
                    if(dis[j][k] == INF) continue;//没边
                    if(1LL * f[i | (1 << (k - 1))] > 1LL * f[i] + 1LL * dep[i][j] * dis[j][k]){
                        f[i | (1 << (k - 1))] = f[i] + dep[i][j] * dis[j][k];
                        memcpy(dep[i | (1 << (k - 1))],dep[i],sizeof(dep[i | (1 << (k - 1))]));
                        dep[i | (1 << (k - 1))][k] = dep[i][j] + 1;
                    }
                }
            }
        }
        return f[(1 << n) - 1];
    }
    int main()
    {
        n = read(),m = read();
        memset(dis,INF,sizeof(dis));
        while(m--){
            int u,v,w;u = read(),v = read(),w = read();
            dis[u][v] = dis[v][u] = min(dis[u][v],w);
        }
        int ans = 1000000000;//这里用了INF就会变成63..
        for(int i = 1;i <= n;++i){
            ans = min(ans,solve(i));
        }
        printf("%d
    ",ans);
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    浅析一类要求相邻不同的环上染色问题
    中国剩余定理(CRT)及其扩展(ExCRT)
    bsoj5988 [Achen模拟赛]期望 题解
    涂色游戏 题解
    [JZOJ A组]球 题解
    由 [SDOI2012]Longge的问题 探讨欧拉函数和莫比乌斯函数的一些性质和关联
    [NOIP模拟]文本编辑器 题解
    Nilearn 小记
    django 开发笔记1
    浅谈无需工作量证明的加密货币
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/14333326.html
Copyright © 2020-2023  润新知