zoukankan      html  css  js  c++  java
  • HDU 3920 Clear All of Them I(DP + 状态压缩 + 贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3920

    题目大意:你在一个位置用激光枪灭敌人,给你初始位置,下面是2*n个敌人的位置,你一枪能杀两个,可以杀死任意两个人,激光束的路径是消耗的能量,求最小能量,保证一次只消灭两个敌人,你的位置不变

    Sample Input
    2
     
     
    0 0
    1
    6 0
    3 0
     
     
    0 0
    2
    1 0
    2 1
    -1 0
    -2 0
     
    Sample Output
    Case #1: 6.00
    Case #2: 4.41

    分析:给每个点编个号,用状态压缩表示射击那些点,射击过的表示为1,dp[i]表示射击状态 i 时最少消耗,答案即为dp[(1<<2*n)-1]

      先每个点到射击点排个序,每次选最近的一个点,和距离这个点最近的点,这两个就是应该选的点(贪心)

    代码如下:

     1 # include<cstdio>
     2 # include<cstring>
     3 # include<algorithm>
     4 # include<iostream>
     5 # include<cmath>
     6 using namespace std;
     7 const int INF = 0xffffff;
     8 double dis[21][21],dp[1<<21];
     9 int vis[1<<21];
    10 int n,fx,fy;
    11 struct NODE
    12 {
    13     int x,y;
    14 } node[21];
    15 double DIS(double x1,double y1,double x2,double y2)
    16 {
    17     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    18 }
    19 bool cmp(NODE a,NODE b)
    20 {
    21     return DIS(a.x,a.y,fx,fy)<DIS(b.x,b.y,fx,fy);
    22 }
    23 double DP(int sta)
    24 {
    25     if(vis[sta])
    26         return dp[sta];
    27     vis[sta] = 1;
    28     if(sta==0)
    29         dp[0]=0.0;
    30     else
    31     {
    32         int i;
    33         for(i=0; i<2*n; i++)
    34         {
    35             if((1<<i) & sta)break;
    36         }
    37         for(int j=i+1; j<2*n; j++)
    38         {
    39             if((sta & (1<<j))==0)continue;
    40             dp[sta]=min(DP(sta^(1<<j)^(1<<i))+dis[i][j],dp[sta]);
    41         }
    42     }
    43     return dp[sta];
    44 }
    45 int main()
    46 {
    47     int T,cas=1;
    48     int i,j;
    49     scanf("%d",&T);
    50     for(cas=1; cas<=T; cas++)
    51     {
    52         scanf("%d%d",&fx,&fy);
    53         scanf("%d",&n);
    54         for(i=0; i<2*n; i++)
    55             scanf("%d%d",&node[i].x,&node[i].y);
    56         sort(node,node+2*n,cmp);
    57         for(i=0; i<2*n; i++)
    58             for(j=i+1; j<2*n; j++)
    59             {
    60                 dis[i][j]=DIS(node[i].x,node[i].y,fx,fy)+DIS(node[i].x*1.0,node[i].y*1.0,node[j].x*1.0,node[j].y*1.0);
    61             }
    62         memset(vis,0,sizeof(vis));
    63         memset(dp,INF,sizeof(dp));
    64         printf("Case #%d: %.2f
    ",cas,DP((1<<(2*n))-1));
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    Unity项目
    Unity基本操作
    博客园自定义主题样式
    明解C语言
    C指针基础知识
    排序算法
    session理解与总结【session原理、应用、与cookie区别】
    cookie理解与实践【实现简单登录以及自动登录功能】
    【数据结构与算法】双指针思想——数组首部或尾部同向遍历
    【数据结构与算法】双指针思想——首尾双向遍历
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3300256.html
Copyright © 2011-2022 走看看