HDU 3362 Fix

题目大意:题目给出n(n <= 18)个点的二维坐标,并说明某些点是被固定了的,其余则没固定,要求添加一些边,使得还没被固定的点变成固定的,当一个没固定的点和两个固定了的点连接后,该点就被间接固定了(三角形的稳定性质),无论是直接固定还是间接固定的点,都可以供以后的点用于固定,添加的边的总长度即为代价

题解:观察数据范围,状压Dp可做,对于当前需要固定的点,在已经是固定状态的点中选出两个距离当前点最小的,这就保证了局部最优,从起始状态开始转移,最后判断能否到达最终目标状态就可以了。

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int n,x[20],y[20],fix[20];
double dp[1<<18];
double dis(int a,int b){
    return sqrt(1.0*(x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])*1.0);
}
double F(int pos,int x){
    double ans=0,d[20];
    bool mark[20];
    for(int i=0;i<n;i++){
        if((1<<i)&pos)mark[i]=1,d[i]=dis(i,x);
        else mark[i]=0;
    }
    for(int i=0;i<2;i++){
        double min=1e9;int p=0;
        for(int j=0;j<n;j++)if(mark[j]&&d[j]<min)min=d[j],p=j;
        ans+=min; mark[p]=0;
    }if(ans>=1e9)return -1;
    return ans;
}
int main(){
    while(scanf("%d",&n),n){
        int begin=0,end=0;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&x[i],&y[i],&fix[i]);
            if(fix[i])begin+=(1<<i);
            end+=(1<<i);
        }
        for(int i=0;i<(1<<n);i++)dp[i]=1e9;dp[begin]=0;
        for(int i=begin;i<end;i++){
            if(dp[i]==1e9)continue;
            for(int j=0;j<n;j++){
                if(i&(1<<j))continue;
                double sum=F(i,j);
                if(sum>0)dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+sum);
            }
        }
        if(dp[end]==1e9)puts("No Solution");
        else printf("%.6lf\n",dp[end]);
    }return 0;
}
时间: 2024-10-17 17:24:34

HDU 3362 Fix的相关文章

HDU 3362 Fix(状压dp)

Fix Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1037    Accepted Submission(s): 349 Problem Description There are a few points on a plane, and some are fixed on the plane, some are not. We

2014 Super Training #1 B Fix 状压DP

原题: HDU 3362 http://acm.hdu.edu.cn/showproblem.php?pid=3362 开始准备贪心搞,结果发现太难了,一直都没做出来.后来才知道要用状压DP. 题意:题目给出n(n <= 18)个点的二维坐标,并说明某些点是被固定了的,其余则没固定,要求添加一些边,使得还没被固定的点变成固定的,可见题目中的图形sample. 由于n很小,而且固定点的顺序没有限制,所以需要用状态压缩DP. 注意:1.当一个没固定的点和两个固定了的点连接后,该点就被(间接)固定了(

HDU 4334 Trouble(hash + 枚举)

HDU 4334 题意: 给五个数的集合,问能否从每个集合中取一个数,使五个数之和为0. 思路: 集合大小是200,直接枚举的复杂度是200^5,一定会超时. 直接枚举的上限是3层,我们可以将枚举剩下两个集合各任取一个元素可能组成的元素和,并将其作hash处理,使我们能很快判断枚举出来的三个集合元素和在剩下的两个集合里是否有相应元素匹配. code: /* * @author Novicer * language : C++/C */ #include<iostream> #include&l

hdu 4217 Data Structure?/treap

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4217 可用线段树写,效率要高点. 这道题以前用c语言写的treap水过了.. 现在接触了c++重写一遍... 不带重复元素的插入删除第k大带垃圾回收,具体如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<algorithm> 5 typedef long long

转载:hdu 题目分类 (侵删)

转载:from http://blog.csdn.net/qq_28236309/article/details/47818349 基础题:1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056.1058.1061.1070.1076.1089.1090.1091.1092.1093. 1094.1095.1096.1097.1098.1106.1108.1157.116

HDU 4902 Nice boat 多校4 线段树

给定n个数 第一个操作和普通,区间覆盖性的,把l-r区间的所有值改成固定的val 第二个操作是重点,输入l r x 把l-r区间的所有大于x的数,变成gcd(a[i],x) a[i]即指满足条件的序列上的数值 最后才输出所有值 当时苦思这个地方如何优化,想着不可能单点去更新吧,但是区间gcd,不能保存下来,一来他是要>x才有效,本来聪哥想了一种先把各种x gcd一遍,最后在push下去,发现不行,就是因为他对>x才有效,你在区间就直接gcd了,那不是把不该gcd的也给搞了 还想过说先存起来所有

HDU 4309 Seikimatsu Occult Tonneru

Seikimatsu Occult Tonneru Time Limit: 6000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 430964-bit integer IO format: %I64d      Java class name: Main During the world war, to avoid the upcoming Carpet-bombing from The Thi

HDU 4116 Fruit Ninja

http://acm.hdu.edu.cn/showproblem.php?pid=4116 题意:给N个圆,求一条直线最多能经过几个圆?(相切也算) 思路:枚举中心圆,将其他圆的切线按照极角排序,并赋上权值(1\-1),那么我们for一遍,sum随时加上权值,当sum最大时,就可以更新答案. #include<cstdio> #include<cmath> #include<iostream> #include<algorithm> #include<

hdu 3288 Resource Allocation

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3288 Resource Allocation Description HDU-Sailormoon is made up of three girls~~~wj, xq, lff, usually they work together ---- solve a variety of problems. So they has to use some resources in the process.