题目大意:给定一张图,每个点及两两之间的距离已经给出,下面给出m个点,问:
从0开始,怎样走经过下面所有这m个点得到的距离值之和可以达到最小。数据范围很小,可以直接暴搜,
搜出给定数组的全排列,计算出每个排列的距离值之和,不断更新求最小值即可完美解决该题。
/********************** * author:crazy_石头 * Pro:HDOJ 1572 * algorithm:dfs * Time:0ms * Judge Status:Accepted ***********************/ #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <set> #include <vector> #include <cmath> using namespace std; #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define ms(a,b) memset((a),(b),sizeof(a)) #define INF 1<<29 const int maxn=1000+5; int dis[maxn][maxn],a[maxn];//a数组存储每次全排列之后下标的可能结果,dis数组则用来记录距离; int temp[maxn];//h数组记录点; bool used[maxn]; int n,m; int res,ans; inline int min(int a,int b) { return a<b?a:b; } inline void cal() { ans=dis[0][temp[0]];//每个dfs序列得到的距离取最小值; rep(i,1,m-1) { ans+=dis[temp[i-1]][temp[i]]; } res=min(ans,res); } inline void dfs(int cur) { if(cur==m) { cal(); return ; } else { rep(i,0,m-1) { if(!used[i]) { used[i]=1; temp[cur]=a[i]; dfs(cur+1); used[i]=0; } } } } int main() { while(~scanf("%d",&n)&&n) { rep(i,0,n-1) { rep(j,0,n-1) { scanf("%d",&dis[i][j]); } } res=INF; scanf("%d",&m); rep(i,0,m-1) scanf("%d",&a[i]); ms(used,0); ms(temp,0); dfs(0); printf("%d\n",res); } return 0; } |
* This source code was highlighted by YcdoiT. ( style: Friend )