标签:vis int des 暴走 蓝桥 tim 逗志芃 妹子
题目来源:蓝桥杯算法训练
知识点:搜索、Floyd算法
问题描述
逗志芃是有妹子的现充,但是有时候妹子就是烦恼。因为逗志芃太逗了,所以这段时间妹子对逗志芃发动了技能无理取闹,妹子要去玩很多的景点。由于逗志芃之前抽机花费了太多的时间,不久以后又要微积分考试了,所以现在被妹子搞成暴走状态了。但是妹子永远是上帝,所以逗志芃只能带妹子出去玩,不过为了节约时间,他希望找到一条花费时间最少的一次性游览线路。
输入格式
第一行1个数n,表示逗志芃所在的城市有多少个景点,接下来是一个n*n的矩阵。a(i,j)表示i号景点到j号景点的路上花费的时间是多少。
接下来是一个数m,表示逗志芃妹子要去去的景点数目。由于妹子在无理取闹,所以可能会有重复的景点,不过只要去一次就可以了。接下来是m个数,就是妹子要去的景点编号。
输出格式
一个数,最少的花费时间。
样例输入
3
0 1 2
1 0 3
2 3 0
3
2 3 1
样例输出
3
数据规模和约定
0<n<=30,0<m<=20,时间<=1000000
题目分析
本题可以看成是图问题中寻找最短路径的变体,只是在这里一个顶点可以经过多次。这里的图是一个完全图,数组a[i][j]
表示从地点i
到地点j
需要的时间。
可以发现,直接从地点i
到地点j
可能时间较长,而先从地点i
到地点k
,再从地点k
到地点j
能获得更短的时间。因此,在 DFS 搜索前先使用弗洛伊德算法对n*n
的矩阵进行处理,获得元素a[i][j]
的最小值。然后在图上进行 DFS 搜索即可。
关于弗洛伊德算法可以自行查找,本质就是本代码中preprocess()
函数的意思。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAX = 35;
int tim[MAX][MAX];
int des[MAX];
int vis[MAX];
int n, m, num;
int ans;
void preprocess() {
for(int k=1; k<=n; ++k){
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
tim[i][j] = min(tim[i][j],tim[i][k]+tim[k][j]);
}
}
}
}
void dfs(int cur, int cnt, int t) {
if(cnt == num) {
ans = min(ans, t);
return;
}
for(int i=1; i<=n; i++) {
if(des[i] && !vis[i] && tim[cur][i]+t <= ans) {
vis[i] = 1;
dfs(i, cnt+1, t+tim[cur][i]);
vis[i] = 0;
}
}
}
int main() {
cin >> n;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
cin >> tim[i][j];
}
}
preprocess();
cin >> m;
int a;
num = 0;
memset(des, 0, sizeof(des));
for(int i=1; i<=m; i++) {
cin >> a;
if(!des[a]) {
num++;
des[a] = 1;
}
}
ans = 1e6;
for(int i=1; i<=n; i++) {
if(des[i]) {
memset(vis, 0, sizeof(vis));
vis[i] = 1;
dfs(i, 1, 0);
}
}
cout << ans << endl;
return 0;
}
标签:vis,int,des,暴走,蓝桥,tim,逗志芃,妹子 来源: https://blog.csdn.net/weixin_45688536/article/details/123034425
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。