每日刷题35

资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
  逗志芃是有妹子的现充,但是有时候妹子就是烦恼。因为逗志芃太逗了,所以这段时间妹子对逗志芃发动了技能无理取闹,妹子要去玩很多的景点。由于逗志芃之前抽机花费了太多的时间,不久以后又要微积分考试了,所以现在被妹子搞成暴走状态了。但是妹子永远是上帝,所以逗志芃只能带妹子出去玩,不过为了节约时间,他希望找到一条花费时间最少的一次性游览线路。
输入格式
  第一行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

解答:
利用佛洛依德算法先求最短路径,接着用dfs进行图的遍历操作;

#include<iostream>
using namespace std;
const int N=32;
int dp[N][N],n,visit[N],des[N],m,num;//其中visit是在dfs中进行访问的数组,des是在main中访问节点的矩阵
int result=1e6;
void floyd(int (*a)[N],int n){
    
    
    for(int i = 1;i<=n;i++){
    
    
        for(int j = 1;j<=n;j++){
    
    
            for(int k =1;k<=n;k++){
    
    
                if(a[i][j]>a[i][k]+a[k][j])
                    a[i][j]=a[i][k]+a[k][j];
            }
        }
    }
}
void dfs(int cur, int cnt, int t) {
    
    
	if(cnt == num) {
    
    
		result = min(result, t);
		return;
	}
	for(int i=1; i<=n; i++) {
    
    
		if(des[i] && !visit[i] && dp[cur][i]+t <= result) {
    
    
			visit[i] = 1;
			dfs(i, cnt+1, t+dp[cur][i]);
			visit[i] = 0;
		}
	}
}

int main(){
    
    
    int a;
    cin >> n;
    for(int i = 1;i<=n;i++){
    
    
        for(int j = 1;j<=n;j++){
    
    
            cin >> dp[i][j];
        }
    }
    floyd(dp,n);
    cin >> m;
    for(int i = 1;i<=m;i++){
    
    
        cin >> a;
        if(!des[a]){
    
    
            des[a]=1;
            num++;
        }
    }
    for(int i =1;i<=n;i++){
    
    
        if(des[i]){
    
    
        for(int j =1;j<=n;j++)//这一步的操作是要把全部点置为0,因为原来我们从一个点开始遍历但是dfs算法无法把最开始的点置为零,因此每次dfs之前要置零
            visit[j]=0;
        visit[i]=1;
        dfs(i,1,0);
        }
    }
    cout<<result;
}

猜你喜欢

转载自blog.csdn.net/weixin_47988292/article/details/129949296