zoukankan      html  css  js  c++  java
  • uva3695

    题意是给出平面上的n个点,找一个矩形使得边界上包含的点最多。

    Sol

    经典套路是减小枚举的范围。

    最暴力的方法是枚举四条边界然后O(n)判断,一共的时间复杂度是O(n5)。

    优化的方法是只枚举矩形的上下边界,用奇技淫巧确定左右边界。(一种类似前缀和的思想)

    枚举完上下边界之后只需要O(n)扫一遍处理好三个数组,之后再以类似uva11078的思路O(n)求解。

    时间复杂度O(n3)

    对于上下边界的枚举,我们可以先处理出存储y信息的数组,之后对该数组进行去重,如此大大方便了上下边界的枚举。

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 105;
    
    int n, kase;
    
    int on[maxn], on2[maxn], left[maxn], y[maxn];
    
    struct point
    {
        int x, y;
        bool operator < (const point& rhs) const
        {
            return x < rhs.x;
        }
    }p[maxn];
    
    int work()
    {
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d", &p[i].x, &p[i].y);
            y[i] = p[i].y;//套路
        }
        sort(p + 1, p + 1 + n);
        sort(y + 1, y + 1 + n);
        int m = unique(y + 1, y + n + 1) - y - 1;
        if (m <= 2)
        {
            return n;
        } 
        int ans = 0;
        for (int a = 1; a < m; a++)
            for (int b = a + 1; b <= m; b++)
            {
                int ymin = y[a], ymax = y[b];
                
                int k = 0;
                for (int i = 1; i <= n; i++)
                {
                    if (i == 1 || p[i].x != p[i - 1].x)//出现了一条新的竖线
                    {
                        k++;
                        on[k] = on2[k] = 0;//相当于初始化on[],on2[] 
                        left[k] = left[k - 1] + on2[k - 1] - on[k - 1];//用上一个left递推现在这个left
                    }
                    if (p[i].y > ymin && p[i].y < ymax) on[k]++;
                    if (p[i].y >= ymin && p[i].y <=ymax) on2[k]++;
                }
                if (k <= 2)
                {
                    return n;
                }
                
                int mx = 0;//uva11078的思路
                for (int j = 1; j <= k; j++)
                {
                    ans = max(ans, left[j] +on2[j] + mx);
                    mx = max(mx, on[j] - left[j]);
                }
            }
        return ans;
    }
    
    void solve()
    {
        kase++;
        printf("Case %d: %d
    ", kase, work());
    }
    
    int main()
    {
        while (scanf("%d", &n) && n) solve();
        return 0;
    } 
  • 相关阅读:
    poj3225(区间操作,交,并,补)
    uva11235
    hdu1166(树状数组)
    uva11997
    uva11991
    uva 11995
    2017 Multi-University Training Contest
    Maven设置使用自定义的jar包到自己本地仓库
    Springboot之从数据库读取配置信息进行注入
    Springboot中为什么需要采用Service+ServiceImpl的结构?
  • 原文地址:https://www.cnblogs.com/yohanlong/p/7703994.html
Copyright © 2011-2022 走看看