zoukankan      html  css  js  c++  java
  • hdu 4562 守护雅典娜 (Simple Geometry + dp)

    http://acm.hdu.edu.cn/showproblem.php?pid=4562

      中文题。

      这道题的做法是先筛选出那些能够起到分隔雅典娜和怪兽的圆,就是那些只包围雅典娜或者只包围怪兽的圆,这样就分离出两种圆。因为不能同时对这两种圆进行dp,所以我们可以分别dp出最优解之后再对两种圆的最优解进行合并。这种dp就像是LIS,我们需要先对圆的大小进行排序,保证的是大的圆围在小的圆外面,这样就可以避免判断当前圆是否跟那个圆集里任何一个圆相交。

    代码如下:

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 
     8 using namespace std;
     9 
    10 struct Circle {
    11     int x, y, r;
    12 } ;
    13 
    14 struct Point {
    15     int x, y;
    16 } mon, ath;
    17 
    18 template <class T> T sqr(T x) { return x * x;}
    19 vector<Circle> vath, vmon;
    20 
    21 bool cmp(Circle a, Circle b) { return a.r < b.r;}
    22 
    23 bool check(Circle a, Circle b) {
    24     int dis = sqr(a.x - b.x) + sqr(a.y - b.y);
    25     int dr = sqr(a.r - b.r), sr = sqr(a.r + b.r);
    26     return !(dr <= dis && dis <= sr);
    27 }
    28 
    29 bool inCir(Point x, Circle a) {
    30     int dis = sqr(x.x - a.x) + sqr(x.y - a.y), r2 = sqr(a.r);
    31     return dis < r2;
    32 }
    33 
    34 bool onCir(Point x, Circle a) {
    35     int dis = sqr(x.x - a.x) + sqr(x.y - a.y), r2 = sqr(a.r);
    36     return dis == r2;
    37 }
    38 
    39 int dp1[1111], dp2[1111];
    40 
    41 int main() {
    42 //    freopen("in", "r", stdin);
    43     int T, n;
    44     cin >> T;
    45     Circle tmp;
    46     for (int cas = 1; cas <= T; cas++) {
    47         cin >> n >> mon.x >> mon.y;
    48         ath.x = ath.y = 0;
    49         vath.clear(), vmon.clear();
    50         while (n--) {
    51             cin >> tmp.x >> tmp.y >> tmp.r;
    52             bool a = inCir(ath, tmp), b = inCir(mon, tmp);
    53             if (!onCir(ath, tmp) && !onCir(mon, tmp) && (a ^ b)) { // 分离出有用的圆
    54                 if (a) vath.push_back(tmp);
    55                 else vmon.push_back(tmp);
    56             }
    57         }
    58         int sz1 = vath.size(), sz2 = vmon.size();
    59         sort(vath.begin(), vath.end(), cmp);
    60         sort(vmon.begin(), vmon.end(), cmp);
    61         int mx = 0;
    62         for (int i = 0; i < sz1; i++) { // 对包围雅典娜的圆dp
    63             dp1[i] = 0;
    64             for (int j = 0; j < i; j++) {
    65                 if (check(vath[i], vath[j])) dp1[i] = max(dp1[i], dp1[j]);
    66             }
    67             dp1[i]++;
    68             mx = max(mx, dp1[i]);
    69 //            cout << dp1[i] << ' ';
    70         }
    71 //        cout << endl;
    72         for (int i = 0; i < sz2; i++) { // 对包围怪兽的圆dp
    73             dp2[i] = 0;
    74             for (int j = 0; j < i; j++) {
    75                 if (check(vmon[i], vmon[j])) dp2[i] = max(dp2[i], dp2[j]);
    76             }
    77             dp2[i]++;
    78             mx = max(mx, dp2[i]);
    79 //            cout << dp2[i] << ' ';
    80         }
    81 //        cout << endl;
    82         for (int i = 0; i < sz1; i++) { // 对两种dp值合并,从而得到所需的答案
    83             for (int j = 0; j < sz2; j++) {
    84                 if (check(vath[i], vmon[j])) {
    85                     mx = max(mx, dp1[i] + dp2[j]);
    86                 }
    87             }
    88         }
    89         printf("Case %d: %d\n", cas, mx);
    90     }
    91     return 0;
    92 }
    View Code

    ——written by Lyon

  • 相关阅读:
    HDU 5336 The mook jong (DP)
    HDU 1686 Oulipo (KMP——统计模式串出现次数)
    hdu 1711Number Sequence (KMP——输出模式串第一次出现位置)
    POJ Borg Maze (BFS+最小生成树)
    POJ 2349 Arctic Network (最小生成树第K大(小)边)
    hdu 1712 ACboy needs your help (dp 分组背包)
    hdu 1181 变形课 (bfs)
    hdu 2069 Coin Change (dp 母函数 )
    hdu 1171 Big Event in HDU(dp 01背包 母函数)
    hdu 1398 Square Coins (母函数)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4562_Lyon.html
Copyright © 2011-2022 走看看