[关闭]
@wsndy-xx 2018-05-05T11:24:03.000000Z 字数 1526 阅读 929

Cogs 线型网络

题解

1

最优组合问题
传统的动态规划算法 的情况下空间、时间、精度
并不优秀
我们尝试使用随机化算法
可以用退火过掉这道题
我们考虑可以枚举全排列进行选择,这样的解一定是最优的
但这样和动态规划没有太大的不同
考虑,如果某次尝试已经得到了一个不错的解,如果大面积打乱就不是一个好的选择,只需改动该排列中的几个位置。

2

下面介绍模拟退火算法在该题中的应用
首先初始化排列
每次改动几个位置后计算出解
如果该解比当前解更优,就接受该解
否则以一定的概率接受该解
这个接受方法在之前提到过

  1. inline bool Accept(DB delta, DB now_t) {
  2. if(delta <= 0) return 1;
  3. return rand() <= exp((- delta) / now_t) * RAND_MAX;
  4. }
  5. inline DB Work() {
  6. DB now_t = Max_t;
  7. Node p;
  8. while(now_t > 0.01) {
  9. Node p2(p);
  10. if(Accept(p2.Dis() - p.Dis(), now_t)) p = p2;
  11. now_t *= Delta;
  12. }
  13. return p.Dis();
  14. }

很显然这个 函数我们要多执行几遍


Code

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <cstdlib>
  6. using namespace std;
  7. const int N = 25;
  8. #define DB double
  9. int n;
  10. DB x[N], y[N], dis[N][N];
  11. const DB Max_t = 10000;
  12. const DB Delta = 0.999;
  13. struct Node {
  14. int path[N];
  15. Node() {
  16. for(int i = 0; i <= n; i ++)
  17. path[i] = i;
  18. }
  19. Node(const Node & a) {
  20. for(int i = 0; i <= n; i ++) path[i] = a.path[i];
  21. std:: swap(path[rand() % n + 1], path[rand() % n + 1]);
  22. }
  23. inline DB Dis() {
  24. DB ret = 0;
  25. for(int i = 1; i <= n; i ++) {
  26. ret += dis[path[i - 1]][path[i]];
  27. }
  28. return ret;
  29. }
  30. };
  31. inline bool Accept(DB delta, DB now_t) {
  32. if(delta <= 0) return 1;
  33. return rand() <= exp((- delta) / now_t) * RAND_MAX;
  34. }
  35. inline DB Work() {
  36. DB now_t = Max_t;
  37. Node p;
  38. while(now_t > 0.01) {
  39. Node p2(p);
  40. if(Accept(p2.Dis() - p.Dis(), now_t)) p = p2;
  41. now_t *= Delta;
  42. }
  43. return p.Dis();
  44. }
  45. int main() {
  46. freopen("linec.in", "r", stdin);
  47. freopen("linec.out", "w", stdout);
  48. srand(220180505);
  49. std:: cin >> n;
  50. for(int i = 1; i <= n; i ++) std:: cin >> x[i] >> y[i];
  51. for(int i = 1; i <= n; i ++) {
  52. dis[i][i] = 0;
  53. for(int j = i + 1; j <= n; j ++)
  54. dis[i][j] = dis[j][i] = hypot(x[i] - x[j], y[i] - y[j]);
  55. }
  56. DB Answer = 1e18;
  57. int T = 200;
  58. for(; T; T --) {
  59. DB imp = Work();
  60. Answer = std:: min(Answer, imp);
  61. }
  62. printf("%.2lf", Answer);
  63. return 0;
  64. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注