• [luoguP1433] 吃奶酪(DP || Dfs)


    传送门

    深搜加剪纸可A(O(玄学) 1274ms)

    ——代码

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <iostream>
     4 
     5 int n;
     6 double ans = ~(1 << 31), a[16], b[16];
     7 bool vis[16];
     8 
     9 inline double min(double x, double y)
    10 {
    11     return x < y ? x : y;
    12 }
    13 
    14 inline double query(int x, int y)
    15 {
    16     return sqrt((a[x] - a[y]) * (a[x] - a[y]) + (b[x] - b[y]) * (b[x] - b[y]));
    17 }
    18 
    19 inline void dfs(int now, double sum, int k)
    20 {
    21     if(k == n + 1)
    22     {
    23         ans = min(ans, sum);
    24         return;
    25     }
    26     if(sum > ans) return;
    27     for(int i = 1; i <= n; i++)
    28         if(!vis[i])
    29         {
    30             vis[i] = 1;
    31             dfs(i, sum + query(now, i), k + 1);
    32             vis[i] = 0;
    33         }
    34 }
    35 
    36 int main()
    37 {
    38     scanf("%d", &n);
    39     for(int i = 1; i <= n; i++) scanf("%lf %lf", &a[i], &b[i]);
    40     dfs(0, 0, 1);
    41     printf("%.2lf
    ", ans);
    42     return 0;
    43 }
    View Code

    然而状压DP,稳一手(据说O(n2*2n) 73ms)

    采用记忆化搜索。

    设f[i][S]为已经走过的点的集合为S,当前停留在点i的最短距离

    f[i][S] = f[j][S - i] + dis(i, j) (i, j ∈ S && i != j)

    ——代码

     1 #include <cmath>
     2 #include <cstdio>
     3 
     4 const int INF = 1e9;
     5 int n;
     6 double ans, a[16], b[16], f[16][1 << 16];
     7 
     8 inline double dist(int i, int j)
     9 {
    10     return sqrt((a[i] - a[j]) * (a[i] - a[j]) + (b[i] - b[j]) * (b[i] - b[j]));
    11 }
    12 
    13 inline double min(double x, double y)
    14 {
    15     return x < y ? x : y;
    16 }
    17 
    18 inline int istrue(int x, int S)
    19 {
    20     return (1 << x - 1) & S;
    21 }
    22 
    23 inline int set0(int x, int S)
    24 {
    25     return (~(1 << x - 1)) & S;
    26 }
    27 
    28 inline void dfs(int now, int S)
    29 {
    30     if(f[now][S] != -1) return;
    31     f[now][S] = INF;
    32     for(int i = 1; i <= n; i++)
    33     {
    34         if(i == now) continue;
    35         if(!istrue(i, S)) continue;
    36         dfs(i, set0(now, S));
    37         f[now][S] = min(f[now][S], f[i][set0(now, S)] + dist(i, now));
    38     }
    39 }
    40 
    41 int main()
    42 {
    43     int i, j;
    44     scanf("%d", &n);
    45     for(i = 1; i <= n; i++) scanf("%lf %lf", &a[i], &b[i]);
    46     for(i = 1; i <= n; i++)
    47         for(j = 1; j < (1 << n); j++)
    48             f[i][j] = -1;
    49     for(i = 1; i <= n; i++) f[i][1 << i - 1] = dist(0, i);
    50     for(i = 1; i <= n; i++) dfs(i, (1 << n) - 1);
    51     ans = INF;
    52     for(i = 1; i <= n; i++) ans = min(ans, f[i][(1 << n) - 1]);
    53     printf("%.2lf
    ", ans);
    54     return 0;
    55 }
    View Code

    用递推更简便(68ms)

    ——代码

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 const int INF = 1e9;
     6 int n, m;
     7 double ans, a[16], b[16], f[16][1 << 16];
     8 
     9 inline double dist(int i, int j)
    10 {
    11     return sqrt((a[i] - a[j]) * (a[i] - a[j]) + (b[i] - b[j]) * (b[i] - b[j]));
    12 }
    13 
    14 inline double min(double x, double y)
    15 {
    16     return x < y ? x : y;
    17 }
    18 
    19 int main()
    20 {
    21     int i, j, S, x, y;
    22     scanf("%d", &n);
    23     m = (1 << n) - 1;
    24     for(i = 1; i <= n; i++) scanf("%lf %lf", &a[i], &b[i]);
    25     memset(f, 0x7f, sizeof(f));
    26     for(i = 1; i <= n; i++) f[i][1 << i - 1] = dist(0, i);
    27     for(S = 1; S <= m; S++)
    28         for(i = 1; i <= n; i++)
    29         {
    30             if(!((1 << i - 1) & S)) continue;
    31             for(j = 1; j <= n; j++)
    32             {
    33                 if(i == j) continue;
    34                 if(!((1 << j - 1) & S)) continue;
    35                 f[i][S] = min(f[i][S], f[j][(1 << i - 1) ^ S] + dist(j, i));
    36             }
    37         }
    38     ans = INF;
    39     for(i = 1; i <= n; i++) ans = min(ans, f[i][m]);
    40     printf("%.2lf
    ", ans);
    41     return 0;
    42 }
    View Code
  • 相关阅读:
    HTML-DOM实例——实现带样式的表单验证
    HTML-DOM常用对象的用法(select/option/form/table)
    C++程序嵌入Python解释器二次开发
    线程池、协程
    Qt信号(SINGAL)与槽(SLOT)
    随机数
    字符串、内存拷贝
    模板元编程以及关键字template和typename
    std::thread,std::future,std::promise,std::async
    C++智能指针,RAII(资源获取即初始化) 原则
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6909846.html
Copyright © 2020-2023  润新知