zoukankan      html  css  js  c++  java
  • [题解]宝藏(状压

    数据范围小,不是爆搜就是状压

    发现每个集合s不能表示所有状态,还有一个状态是和起始点的距离,这样我们直接用$f[x][s][d]$表示点x在点集s深度为d的最小代价,暴力枚举每个起始点直接扩展状态,把s跑满就更新答案,图上所以dfs实现还好写

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    const int inf=1e9+7;
    const int maxn=15;
    int n,m,g[maxn][maxn],ans=inf,lim;
    int dis[maxn],f[maxn][1<<maxn][maxn];//x在点集s中深度为k的最小代价 
    inline void dfs(int s,int sum,int dep){
        if(sum>=ans)return;
        if(s==lim){ans=sum;return;}
        for(int i=1;i<=n;i++){
            if(!(1<<(i-1)&s))continue;
            for(int j=1;j<=n;j++)
            if(!(1<<(j-1)&s)&&g[i][j]!=0x3f3f3f3f)//没有选过j且ij之间有边 
            if(f[j][1<<(j-1)|s][dep+1]>sum+dis[i]*g[i][j]){
                f[j][1<<(j-1)|s][dep+1]=sum+dis[i]*g[i][j];
                dis[j]=dis[i]+1;
                dfs(1<<(j-1)|s,f[j][1<<(j-1)|s][dep+1],dep+1);
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);lim=(1<<n)-1;
        memset(g,0x3f,sizeof(g));
        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            g[u][v]=g[v][u]=min(g[u][v],w);
        }
        for(int i=1;i<=n;i++){
            memset(dis,0x3f,sizeof(dis));
            memset(f,0x3f,sizeof(f));
            dis[i]=1;
            dfs(1<<(i-1),0,0);
        }
        printf("%d",ans);
    }
  • 相关阅读:
    Excel如何根据基类标红重复内容
    使用FRP配置Windows远程控制
    CentOS 7安装gevent
    CentOS7安装pip
    把音频文件压缩变小的方法
    Linux中nohup和&的用法和区别
    Windows下安装redis服务
    TFS解锁命令
    linux下用rpm 安装jdk
    avascript的匿名函数
  • 原文地址:https://www.cnblogs.com/superminivan/p/11646674.html
Copyright © 2011-2022 走看看