NOIP2017提高组宝藏 (teasure.cpp)

    这题主要用状态压缩dp搜索每种方案找到最优值

```
#include <bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
int n,m,G[15][15],dp[1<<13],dis[15],ans=INF;//G为临接矩阵,dp为每种状态时的最小花费 dis[j]为当前方案时第j块的深度 ans为结果
void dfs(int x){//x为当前状态
    for(int i=1;i<=n;i++){
        if((1<<(i-1))&x){//如果i块在当前状态下已经有道路通了
            for(int j=1;j<=n;j++){
                if(!(1<<(j-1)&x)&&G[i][j]){//第j块未通 且i,j之间有路
                    if(dp[1<<(j-1)|x]>dp[x]+dis[i]*G[i][j]){//从当前状态再修一条i到j的路花费是否比现在的小  1<<(j-1)|x 为把当前状态加上j这个点
                        int tmp=dis[j];//保留现场
                        dis[j]=dis[i]+1;//更新深度
                        dp[1<<(j-1)|x]=dp[x]+dis[i]*G[i][j];//计算花费
                        dfs(1<<(j-1)|x);//继续搜索
                        dis[j]=tmp;//还原现场
                    }
                }
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){//构图
        int x,y,w;
        cin>>x>>y>>w;
        if(G[x][y]==0){
            G[x][y]=w;
            G[y][x]=w;
        }else{
            if(G[x][y]>w){
                G[x][y]=w;
                G[y][x]=w;
            }
        }
    }
    for(int i=1;i<=n;i++){//以i为起点修路
        memset(dis,63,sizeof(dis));
        for(int j=1;j<=(1<<n)-1;j++)dp[j]=INF;//初始化
        dis[i]=1;dp[1<<(i-1)]=0;//起点深度为1 仅有这一个点时花费为0因为有人帮忙修
        dfs(1<<(i-1)); 搜索
        ans=min(ans,dp[(1<<n)-1]);//(1<<n)-1为所有都通路了的状态的花费  更新最小值
    }

    cout<<ans;
    return 0;
}
```


猜你喜欢

转载自blog.csdn.net/qq_39591454/article/details/80866345