列表

详情


MT23. 友好城市

描述

某国家一共有 n 座城市,有的城市与城市与城市之间有路相连,所有的路都是无向的, n 个城市可以通过道理相互达到,其中 2k 座城市是重要城市,国王希望把这 2k 座城市两两配对,形成 k 对友好城市。
友好城市之间常常需要进行交流,因此国王希望友好城市之间的距离不要太长,于是他定义两个城市 u,v 配对的代价为 u,v 之间最短路的长度,2k 座城市配对的总代价为 k 对城市配对的代价和。
国王想知道配对的最小代价。
数据范围:

输入描述

第一行输入一个数 n ,表示城市个数。 接下来输入一个 n*n 的邻接矩阵 A , A[i][j] 表示城市 i 和 城市 j 之间边的长度,如果 A[i][j] = -1,表示 i 和 j 之间没有直接相连的边,输入保证 A[i][j] = A[j][i] ,A[i][i] = -1 ,且 n 个城市相互连通。 最后输入一个数 k ,接下来一行 2k 个数,这 2k 个重要城市的编号

输出描述

输出一个数,最小匹配代价

示例1

输入:

4
-1 2 -1 10
2 -1 3 -1
-1 3 -1 1
10 -1 1 -1
2
1 2 3 4

输出:

3

原站题解

C++ 解法, 执行用时: 25ms, 内存消耗: 428KB, 提交时间: 2020-10-29

 #include <bits/stdc++.h>
using namespace std;

int n, k, a[101][101], b[101], Min=INT_MAX;

void DFS(int cnt, int s){
    if(cnt==2*k){
        Min = min(Min, s);
        return;
    }
    for(int i=cnt+1;i<2*k;i++){
        swap(b[i], b[cnt+1]);
        DFS(cnt+2, s+a[b[cnt]][b[cnt+1]]);
        swap(b[i], b[cnt+1]);
    }
}

int main(){
    scanf("%d", &n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d", &a[i][j]);
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j && a[i][k]!=-1 && a[k][j]!=-1){
                    if(a[i][j]==-1)
                        a[i][j] = a[i][k] + a[k][j];
                    else
                        a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
                }
    scanf("%d", &k);
    for(int i=0;i<2*k;i++)
        scanf("%d", &b[i]);
    DFS(0, 0);
    printf("%d\n", Min);
    return 0;
}

C++14 解法, 执行用时: 25ms, 内存消耗: 440KB, 提交时间: 2020-10-05

#include<bits/stdc++.h>
using namespace std;
int n,k,a[101][101],b[101],Min=-1;

void DFS(int count,int ans){
    
    if(count==2*k){
        if(Min==-1){
            Min = ans;
        }
        else{
            if(Min>ans)
                Min=ans;
            
        }
        return;
    }
    for(int i =count+1;i<2*k;i++){
        swap(b[i],b[count+1]);
        DFS(count+2,ans+a[b[count]][b[count+1]]);
        swap(b[i],b[count+1]);
        
    }
    
}



int main(){
    scanf("%d",&n);
    for ( int i =1;i<=n;i++)
        for(int j = 1;j<=n;j++)
            scanf("%d",&a[i][j]);
    for(int k = 1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j =1;j<=n;j++){
                if(i!=j&& a[i][k]!=-1 && a[k][j]!=-1){
                    if(a[i][j]==-1)
                        a[i][j]=a[i][k]+a[k][j];
                    else
                        if(a[i][j]>a[i][k]+a[k][j])
                            a[i][j]=a[i][k]+a[k][j];
                }
            }
    scanf("%d",&k);
    for(int i =0;i<2*k;i++)
        scanf("%d",&b[i]);
    DFS(0,0);
    printf("%d\n",Min);
    return 0 ;
}

上一题