洛谷 P3959 宝藏 【状压dp or 深度优先搜索】

洛谷 P3959 宝藏

Description:

题目描述还是看链接吧,洛谷 markdown 复制过来有问题,不好意思,辛苦你们了。

题解:

这题看 dalao 们的题解都是什么随机算法,模拟退火。。。吓得我慌忙跑路。

蒟蒻的我只好用 状压dp 来水过。但这里还加了点深度优先搜索的味道

枚举每个起点, dis[i] 表示第 i 个点到起点的经过的宝藏的个数,f[i] 表示状态,表示当前找到宝藏的状态为 i 时,花费的代价的最小值。

然后我们开始深搜,用位运算更新状态,用最短路的思想更新距离,枚举每一个相邻的节点,搜完回溯就可以了。如此轻松快乐地水过此题。

表示依旧对 模拟退火 心有余悸!!!

贴代码:

 1 #include<bits/stdc++.h>
 2 #define inf 2147483647
 3 using namespace std;
 4 int n,m,g[20][20],f[10000],dis[20],ans=inf;
 5 inline void search(int x)
 6 {
 7     for (int i=1; i<=n; i++)
 8     if (1<<(i-1)&x)
 9     {
10         for (int j=1; j<=n; j++)
11           if (((1<<(j-1))&x)==0 && g[i][j]!=inf)
12           {
13               if (f[x|(1<<j-1)]>f[x]+dis[i]*g[i][j])
14               {
15                   int tmp=dis[j];
16                   dis[j]=dis[i]+1;
17                   f[x|(1<<(j-1))]=f[x]+dis[i]*g[i][j];
18                   search(x|(1<<(j-1)));
19                   dis[j]=tmp;
20               }
21           }
22     }
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&m);
27     for (int i=1; i<=n; i++)
28       for (int j=1; j<=n; j++)
29         g[i][j]=inf;
30     int u,v,z;
31     for (int i=1; i<=m; i++)
32     {
33         scanf("%d%d%d",&u,&v,&z);
34         g[u][v]=min(g[u][v],z);
35         g[v][u]=min(g[v][u],z);
36     }
37     for (int k=1; k<=n; k++)
38     {
39         for (int i=1; i<=n; i++) dis[i]=inf;
40         for (int i=1; i<=(1<<n)-1; i++) f[i]=inf;
41         dis[k]=1; f[1<<(k-1)]=0;
42         search(1<<(k-1)); ans=min(ans,f[(1<<n)-1]);
43     }
44     printf("%d",ans);
45     return 0;
46 }
View Code

加油加油加油!!!fighting fighting fighting!!!

原文地址:https://www.cnblogs.com/Frank-King/p/9340688.html