• HDU 3362 Fix


    状压DP。

    首先很容易想到:一个点要被固定的话,必须有两个已经固定了的点与这个点连边。

    再看N的范围,秒想到状压DP,秒出思路。1表示这个点已经被固定,0表示还没被固定。

    推导某个状态的时候,枚举一下这个状态下所有被固定的点哪个是最后被固定的,即可得出这个状态的最优解。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int n;
    struct Point
    {
        int x;
        int y;
        int flag;
    }p[20];
    double dp[600000];
    double dis[20][20];
    double tmp[20];
    int base[20];
    
    bool cmp(const Point&a, const Point&b)
    {
        return a.flag>b.flag;
    }
    
    void read()
    {
        for (int i = 0; i<n; i++)
            scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].flag);
        sort(p, p + n, cmp);
    }
    
    void init()
    {
        for (int i = 0; i < (1 << n) + 10; i++) dp[i] = 999999999.0;
        
        for (int i = 0; i<n; i++)
        {
            for (int j = 0; j<n; j++)
            {
                if (i == j) dis[i][j] = 999999999.0;
                else dis[i][j] = sqrt((p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y)*(p[i].y - p[j].y));
            }
        }
    }
    
    void work()
    {
        int pos = -1;
        for (int i = 0; i<n; i++)
        {
            if (p[i].flag==1) pos = i;
            else break;
        }
    
        if (pos == -1) printf("No Solution
    ");
        else if (pos+1 < 2 )
        {
            if (n != pos + 1) printf("No Solution
    ");
            else printf("0.000000
    ");
        }
        else
        {
            for (int i = 0; i<(1 << (pos + 1)); i++) dp[i] = 0;
            for (int i = pos + 1; i<n; i++)
            {
                int state = (1 << (pos + 1)) - 1 + (1 << i);
                for (int k = 0; k <= pos; k++) tmp[k] = dis[i][k];
                sort(tmp, tmp + pos + 1);
                dp[state] = tmp[0] + tmp[1];
            }
    
            for (int i = (1 << (pos + 1)); i<(1 << n); i++)
            {
                if (dp[i] != 999999999.0) continue;
    
                int temp = i, tot = 0;
                while (temp) base[tot++] = temp % 2, temp = temp / 2;
    
                bool fail = 0;
                for (int k = 0; k <= pos; k++) if (!base[k]) fail = 1;
                if (fail) continue;
    
                for (int k = pos + 1; k < tot; k++)
                {
                    if (base[k])
                    {
                        int u = 0;
                        for (int s = 0; s<tot; s++)
                        {
                            if (s == k) continue;
                            if (base[s]) tmp[u++] = dis[k][s];
                        }
                        sort(tmp, tmp + u);
                        dp[i] = min(dp[i], dp[i - (1 << k)] + tmp[0] + tmp[1]);
                    }
                }
            }
            printf("%.6lf
    ", dp[(1 << n) - 1]);
        }
    }
    
    int main()
    {
        while (~scanf("%d", &n))
        {
            if (!n) break;
            read();
            init();
            work();
        }
        return 0;
    }
  • 相关阅读:
    【3.5】类和实例属性的查找顺序--mro查找
    【3.4】类变量和实例变量
    【3.3】isinstance和type的区别
    【3.2】抽象基类(abc模块)
    【3.1】鸭子类型和多态
    学习笔记 | 浅谈虚拟函数(Virtual Function)
    学习笔记 | Udacity CarND Term 1: Computer Vision and Deep Learning
    命令行 | File Compression in Linux
    Python: if else in a list comprehension
    Topic | Hyperparameter Optimization for Neural Networks
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5197622.html
Copyright © 2020-2023  润新知