一、题目描述
Farmer John 被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。
FJ 已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。
你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过 10^5。
输入格式
第一行农场的个数 N(3 ≤N≤100)。
接下来是一个N×N 的矩阵,表示每个农场之间的距离。理论上,他们是 N 行,每行由 N 个用空格分隔的数组成,实际上,由于每行 80 个字符的限制,因此,某些行会紧接着另一些行。当然,对角线将会是 0,因为不会有线路从第 i 个农场到它本身。
输出格式
只有一个输出,其中包含连接到每个农场的光纤的最小长度
输入输出样例
输入
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
输出
28
二、题解
#include<cstdio>
#include<iostream>
# define INF 65535
using namespace std;
bool vis[20]={false};//标记
int mp[20][20];
int min_s=INF;
int count=1; //count用于计数
int ans,k,n;//ans城市编号,k固定距离
void dfs(int p,int sum)//p城市编号,sum距离之和
{
//用于标记
if(vis[p])
return ;
//当距离大于最小值,之后的就不用进行
if(sum>min_s)
return ;
//如果连通了n个农场
if(count==n)
{
//比较当前距离和与之前记录的最小距离和
//并令其等于最小距离和
if(sum<min_s)
min_s=sum;
return;
}
vis[p]=true;//标记
//一样的深度情况下搜索不同的分支
for(int i = 1 ; i<=n;i++)
{
//printf("%d i\n",i);
if(!vis[i])//这是没有被标记的
{
//连通的农场数量增加
count++;
dfs(i,sum+mp[p][i]);
//回溯
count--;
}
}
//取消标记
vis[p]=false;
}
int main()
{
//输入农场数目
scanf("%d",&n);
//输入各个农场之间的连接费用
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= n ; j++)
scanf("%d",&mp[i][j]);
}
//从第一个城市开始搜索
dfs(1,0);
printf("%d",min_s);
return 0;
}