zoukankan      html  css  js  c++  java
  • poj2008

    题意:给定一些点的坐标(hi,wi),要选出一个点集,使得集合所包含的点数最多,且符合A*(H-h) + B*(W-w) <= C,h为集合中最小h,w为点集中最小w。

    分析:我们是要找到这样的点集,hi>=h,wi>=w,A*(hi-h) + B*(wi-w) <= C。根据线性规划知识,这些点都在一个直角三角形内,两条直角边长度为cw=C/A,ch=C/B。我们的问题转化为用这样一个三角形最多能框住多少点,且根据题意w,h为点集坐标最小值,即三角形两条直角边上都要有点。

    我们的做法是,枚举n个点,对于每个点,先使其处于三角形的直角顶点(左下角),然后向下平移三角形框,每次多加进一个点且要保证我们本次枚举的那个点不出框。看最多的时候能有多少个点在框内。每向下推一下要加进哪些点,除去哪些点我们用一个巧妙的方法来处理。我们用跨越三角形底边的点数减去跨域三角形斜边的点数。我们利用一个将所有点按高度排序的数组,和一个指向该数组的指针,每次枚举一个点,就把指针指向第一位(默认所有点都在线框底边以下),每推一下,就将指针向后移动一些,看有几个点由线框底边以下变为以上。同理我们需要一个按k=A*hi  + B*wi排序的数组。用相同的方法来统计有多少点跨域了斜边。注意不是所有指针掠过的点都是跨越的,需要判断他们的横坐标是否在范围内。

    View Code
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;

    #define maxn 1005

    struct Point
    {
    int w, h, k;
    }point[maxn], *sort_h[maxn], *sort_k[maxn];

    int n, cw, ch, A, B, C;
    int ans, cnt, hnum, knum;

    bool cmph(Point *a, Point *b)
    {
    return a->h > b->h;
    }

    bool cmpk(Point *a, Point *b)
    {
    return a->k > b->k;
    }

    void input()
    {
    scanf("%d", &n);
    scanf("%d%d%d", &A, &B, &C);
    ch = C / A;
    cw = C / B;
    for (int i = 0; i < n; i++)
    {
    scanf("%d%d", &point[i].h, &point[i].w);
    point[i].k = A * point[i].h + B * point[i].w;
    sort_h[i] = &point[i];
    sort_k[i] = &point[i];
    }
    }

    int cal(int h, int w)
    {
    for (; hnum < n && sort_h[hnum]->h >= h; hnum++)
    if (sort_h[hnum]->w >= w && sort_h[hnum]->w <= w + cw)
    cnt++;
    int k = A * h + B * w + C;
    for (; knum < n && sort_k[knum]->k > k; knum++)
    if (sort_k[knum]->w >= w && sort_k[knum]->w <= w + cw)
    cnt--;
    return cnt;
    }

    void work(int a)
    {
    cnt = hnum = knum = 0;
    int w = sort_h[a]->w;
    int h = sort_h[a]->h;
    for (int i = a; i < n && sort_h[i]->h >= h - ch; i++)
    if (sort_h[i]->w >= w && sort_h[i]->w <= w + cw)
    ans = max(ans, cal(sort_h[i]->h, w));
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    input();
    sort(sort_h, sort_h + n, cmph);
    sort(sort_k, sort_k + n, cmpk);
    ans = 0;
    for (int i = 0; i < n; i++)
    work(i);
    printf("%d\n", ans);
    return 0;
    }



  • 相关阅读:
    【算法】三角形最小路径债务
    【阿米巴】债务
    【JTA】JTA允许应用程序执行分布式事务处理
    【算法】代码面试最常用的10大算法
    【Git 】$ ./gradlew idea 构建一个idea的项目
    【git】切换分支获取代码
    【springmvc Request】 springmvc请求接收参数的几种方法
    【gradle】 入门
    项目经理眼中优秀开发人员的标准
    MAC系统介绍
  • 原文地址:https://www.cnblogs.com/rainydays/p/2197120.html
Copyright © 2011-2022 走看看