zoukankan      html  css  js  c++  java
  • 洛谷P1578 奶牛牧场(悬线法思想)

    题目

    悬线法的思想——即扫描线的思想,每个矩阵必定是由两个障碍来构成左右边界或者上下边界。

    如果此两个障碍组成了左右边界,枚举这两个障碍中途更新这两个障碍之间的矩阵上下边界,并且更新最大值。

    考虑如何线性求出两个障碍的矩阵上下边界,

    我们可以把障碍按x坐标排序,然后对于每个障碍,都找x比他大的障碍找一遍,也就是悬线向右扩展,每找一个就更新一下上边界或下边界也就是更新悬线的上下端点, 因为越向右,矩阵的上边界和下边界就逼近矩阵的宽减少,但是矩阵的长却是一直增大的,因此需要每次都更新最大值。

    组成了上下边界同理,最终将漏解的情况加上, 就求出了最优解。

    #include <bits/stdc++.h>
    using namespace std;
    struct dat {
    	int x, y;
    } a[1010000];
    int l, w, n, maxn;
    bool cmp1 (dat a, dat b)
    {return a.y < b.y;}	
    bool cmp2 (dat a, dat b)
    {return a.x < b.x;}	
    inline void init()
    {
    	scanf("%d%d", &l, &w);
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++)
    		scanf("%d%d", &a[i].x, &a[i].y);
    	a[++n].x = 0, a[n].y = w;
    	a[++n].x = l, a[n].y = w;
    	a[++n].x = 0, a[n].y = 0;
    	a[++n].x = l, a[n].y = 0;
    }
    int main()
    {
     	init();
     	sort(a + 1, a + 1 + n, cmp2);//复杂度O(n^2)枚举两个障碍里的面积, 用扫描的思想解决, 
     	for (int i = 1; i <= n; i++)//high为最低的点,low为最高的点 pos为向右扩展的悬线长度,不需要向左,因为前面的向右等同于后面的向左 
     	{
     		int high, low, pos;		
     		high = 0, low = w, pos = l - a[i].x;//pos*(low-high)为当前矩阵面积最大值, 
     		for (int j = i + 1; j <= n; j++)
     		{
     			if (pos * (low - high) <= maxn) break;//如果当前最优解都不能比maxn大,break 
      			maxn = max(maxn, (low - high) * (a[j].x - a[i].x));
     			if (a[j].y >= a[i].y) 		
     				low = min(low, a[j].y);
     			else
     				high = max(high, a[j].y);
     		}
     	}
     	sort(a + 1, a + 1 + n, cmp1);
     	for (int i = 1; i <= n; i++)
     	{
     		int lef, rig, pos;
     		lef = 0, rig = l,  pos = w - a[i].y;//lef为最左边的点,rig为当前最右边的点,pos为向下扩展的悬线长度。 
     		for (int j = i + 1; j <= n; j++)
     		{
     			if (pos * (rig - lef) <= maxn) break;			  
     			maxn = max(maxn, (rig - lef) * (a[j].y - a[i].y));
     			if (a[j].x >= a[i].x)
     				rig = min(rig, a[j].x);
     			else 
     				lef = max(lef, a[j].x);
     		}
     	}
     	for (int i = 1; i < n; i++)//有漏解的情况。
     		maxn = max( maxn, l * ( a[i + 1].y - a[i].y ) );
     	printf("%d", maxn);
     	return 0;
    } 
    
  • 相关阅读:
    面向对象的七大设计原则
    06章 初始继承和多态
    面向太阳,不问春暖花开
    05章 体检套餐管理系统
    02章《深入C#数据类型》项目经理评分
    MongoDB快速入门(十二) -- 索引
    MongoDB快速入门(十一)- sort() 方法
    MongoDB快速入门(十)- Limit(),Skip() 方法
    MongoDB快速入门(九)- 投影
    MongoDB快速入门(八)- 删除文档
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11824309.html
Copyright © 2011-2022 走看看