zoukankan      html  css  js  c++  java
  • 洛谷 P3959 NOIP2017 宝藏 —— 状压搜索

    题目:https://www.luogu.org/problemnew/show/P3959

    搜索;

    不是记忆化,而是剪枝;

    邻接矩阵存边即可,因为显然没有那么多边。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll const inf=0x3f3f3f3f3f3f3f3f;
    int n,m,S,sid[20][20];
    ll s[1<<13],ans,dis[20];
    ll dfs(int p,ll w)
    {
        if(w>=ans)return inf;
        if(p==S)return w;
    //    if(s[p])return s[p];//错误记忆化 
        s[p]=min(s[p],w);//
        ll ret=inf;
        for(int x=1;x<=n;x++)
        {
            if((p&(1<<(x-1)))==0)continue;
            for(int u=1;u<=n;u++)    if(sid[x][u]!=inf&&((1<<(u-1))&p)==0)
            {
                int np=(p|(1<<(u-1)));
                if(s[np]<=w+sid[x][u]*(dis[x]+1))continue;//最优性剪枝 
                dis[u]=dis[x]+1;
                ret=min(ret,dfs(np,w+sid[x][u]*dis[u]));
                dis[u]=0;
            }
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        memset(sid,0x3f,sizeof sid);
        for(int i=1,x,y,z;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            sid[x][y]=min(sid[x][y],z);
            sid[y][x]=sid[x][y];
        }
        ans=inf; S=(1<<n)-1;
        for(int i=1;i<=n;i++)
        {
            memset(s,0x3f,sizeof s);
            ans=min(ans,dfs(1<<(i-1),0));
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    FR #3题解
    L3-005. 垃圾箱分布
    L2-004. 这是二叉搜索树吗?
    L2-002. 链表去重
    L1-009. N个数求和
    L3-003. 社交集群
    L3-004. 肿瘤诊断
    L2-001. 紧急救援
    L3-002. 堆栈
    L2-007. 家庭房产
  • 原文地址:https://www.cnblogs.com/Zinn/p/9375800.html
Copyright © 2011-2022 走看看