HOJ 1572 下沙小面的(2)
思路并不算太难,作为新手,我可能写得很拖沓
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAX 99999999
using namespace std;
const int maxn = 30;
int k, n, a[maxn][maxn], b[8], c[8][8], c0[8];
//k为题目输入的城市数目多少,可能会重复
//n为需要到达的城市数目,不含重复
//a为所有城市之间的距离
//b为需要到达的城市在a中的下标
//c为需要到达的城市之间的距离
//c0为c中每个城市到达的次数
int cmp(int a, int b) {
return a < b;
}
void dfs(int point, int &p, int temp, int &m) {
if (temp == n) {
for(int i = 0; i <=n; i++)//必须每个城市都至少到达一次才算满足任务,否则p和m进行比较没有意义
if (c0[i] == 0) return;
if (p < m)//在每个目标城市都到达过的情况下看目前的路径是否比曾到达过的最短路径更小
m = p;
return;
}
for (int i = 0; i <= n; i++)
if (i != point) {
p += c[point][i];
temp++;//已走过的城市加一
c0[i]++;//i城市走过的次数加一
dfs(i, p, temp, m);//下一步从i城启程
c0[i]--;
p -= c[point][i];
temp--;
}
}
int main() {
int t, p, temp, minRoutine;
while (cin >> t && t != 0) {
n = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
memset(c0, 0, sizeof(c0));
for (int i = 0; i < t; i++)
for (int j = 0; j < t; j++)
cin >> a[i][j];
cin >> k;
int i = 0, x = 0;
while(1){//得到不含重复元素的数组b
int kk;
cin >> kk;
x++;
for (int j = 0; j < i; j++)
if (kk == b[j])
goto A;
b[i++] = kk;
n++;
A:if (x == k)
break;
continue;
}
sort(b, b + n + 1, cmp);//加一是增加一个初始0点,排序
p = 0;//尝试的路径长的
minRoutine = MAX;//走完目的地的路径长度
temp = 0;//以经尝试过的城市数量
for(int i = 0; i <= n; i++)//找出需要用到的城市之间的路长存到c中
for (int j = i; j <= n; j++) {
c[i][j] = a[b[i]][b[j]];
c[j][i] = a[b[j]][b[i]];
}
c0[0] = 1;
dfs(0, p, temp, minRoutine);
cout << minRoutine << endl;
}
return 0;
}