最短路 + 搜索 + 剪枝 之 hdu 4848 Wow! Such Conquering!
// [7/26/2014 Sjm]
/*
此题要求的值是: the minimum sum of all arrival time to each Doge Planet.
先用 Floyd 求任意两点之间的距离,再用 Dfs 去求最优解。。。。
不过关键在剪枝。。能力太水了,一直TLE,,,最后在大神的帮助下过的。。。。
在两个地方剪枝,代码中有说明。。。
*/
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 const int MAX = 35, INF = 0x3f3f3f3f; 8 int n, ans, dis[MAX][MAX], deadline[MAX]; 9 bool used[MAX]; 10 11 void Floyd() { 12 for (int k = 0; k < n; ++k) { 13 for (int i = 0; i < n; ++i) { 14 for (int j = 0; j < n; ++j) { 15 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); 16 } 17 } 18 } 19 } 20 21 void Dfs(int s, int time, int total, int cnt) { 22 if (!cnt) { 23 ans = min(ans, total); 24 return; 25 } 26 // 剪枝位置一:要计算的值已超过当前最优解 27 if (total+cnt*time >= ans) { 28 return; 29 } 30 // 剪枝位置二: 31 // 如果s到i已超过最后期限,那想以s为始点继续深搜,也不会得到解。 32 // (因为:此时dis[s][i]是s到i的最小值, 33 // 即dis[s][x] + dis[x][i] >= dis[s][i],(x是非i的任意一个节点) 34 // 所以若time + dis[s][i] > deadline[i],则以s为始点的其他情况,也必然大于deadline[i]) 35 for (int i = 1; i < n; ++i) { 36 if (!used[i] && time + dis[s][i] > deadline[i]) { 37 return; 38 } 39 } 40 for (int i = 1; i < n; ++i) { 41 if (!used[i]) { 42 used[i] = true; 43 Dfs(i, time + dis[s][i], total + time + dis[s][i], cnt - 1); 44 used[i] = false; 45 } 46 } 47 } 48 49 int main() 50 { 51 //freopen("input.txt", "r", stdin); 52 //freopen("output.txt", "w", stdout); 53 while (~scanf("%d", &n)) { 54 for (int i = 0; i < n; ++i) { 55 for (int j = 0; j < n; ++j) { 56 scanf("%d", &dis[i][j]); 57 } 58 } 59 for (int i = 1; i < n; ++i) { 60 scanf("%d", &deadline[i]); 61 } 62 Floyd(); 63 64 memset(used, false, sizeof(used)); 65 ans = INF; 66 Dfs(0, 0, 0, n-1); 67 if (INF == ans) printf("-1\n"); 68 else printf("%d\n", ans); 69 } 70 return 0; 71 }