zoukankan      html  css  js  c++  java
  • 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种技能
    其它 华硕 ASAU S4100U 系统安装 win10安装 重装系统 Invalid Partition Table 解决
    数据分析 一些基本的知识
    Python 取样式的内容 合并多个文件的样式 自定义样式
    电商 Python 生成补单公司需要的评论格式3
    SpringBlade 本地图片上传 生成缩略图
    SQL Server 字符串截取
    SpringBlade 本地图片上传
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5197622.html
Copyright © 2011-2022 走看看