HDU 4816 Bathysphere (2013长春现场赛D题)

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

 

2013长春区域赛的D题。

 

很简单的几何题,就是给了一条折线。 然后一个矩形窗去截取一部分,求最大面积。

现场跪在这题,最后时刻TLE到死,用的每一小段去三分,时间复杂度是O(n log n) , 感觉数据也不至于超时。

卧槽!!!!代码拷回来,今天在HDU一交,一模一样的代码AC了,加输入外挂6s多,不加也8s多,都可AC,呵呵·····(估计HDU时限放宽了!!!)

现场赛卡三分太SXBK了,我艹!!!! 好好的一个现场赛绝杀错过了。

 

以下是现场赛源码,在HDU顺利AC! 现场TLE到死!

其实O(n)也可以搞,因为是三分的是一个二次函数,求对称轴就可以了。现场没有想到这个优化,等下简单修改成O(n)代码。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <map>
  7 #include <set>
  8 #include <vector>
  9 #include <string>
 10 #include <math.h>
 11 using namespace std;
 12 const int MAXN = 200010;
 13 int x[MAXN],y[MAXN];
 14 int d;
 15 int n;
 16 int L;
 17 int nowx ;
 18 int nextx;
 19 int r1,l2;
 20 const double eps = 1e-8;
 21 double solve()
 22 {
 23     double left = nowx,right = nextx;
 24     double ret1,ret2;
 25     for(int cc = 0;cc <= 30;cc++)
 26     {
 27         double mid = (left + right)/2;
 28         double midmid = (mid + right)/2;
 29         double h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (mid  - x[r1])/(x[r1-1] - x[r1]);
 30         double h2 = y[l2] + (double)(y[l2+1] - y[l2])*(mid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
 31         ret1 = (double)(x[r1] - mid)*(h1 + y[r1])/2 + (double)(mid + 2*d - x[l2])*(h2 + y[l2])/2;
 32         
 33          h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (midmid  - x[r1])/(x[r1-1] - x[r1]);
 34          h2 = y[l2] + (double)(y[l2+1] - y[l2])*(midmid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
 35         ret2 = (double)(x[r1] - midmid)*(h1 + y[r1])/2 + (double)(midmid + 2*d - x[l2])*(h2 + y[l2])/2;
 36         if(ret1 < ret2)
 37             left = mid+eps;
 38         else right = midmid-eps;
 39     }
 40     return ret1;
 41 }
 42 
 43 
 44 int input()
 45 {
 46     char ch;
 47     ch = getchar();
 48     while(ch < '0' || ch >'9')
 49     {
 50         ch = getchar();
 51     }
 52     int ret = 0;
 53     while(ch >= '0' && ch <= '9')
 54     {
 55         ret *= 10;
 56         ret += ch -'0';
 57         ch = getchar();
 58     }
 59     return ret;
 60 }
 61 
 62 int main()
 63 {
 64     //freopen("D.txt","r",stdin);
 65     //freopen("out.txt","w",stdout);
 66     int T;
 67     scanf("%d",&T);
 68     while(T--)
 69     {
 70         scanf("%d%d",&n,&L);
 71         for(int i = 1;i <= n;i++)
 72         {
 73             //x[i] = input();
 74             //y[i] = input();
 75             scanf("%d%d",&x[i],&y[i]);
 76         }
 77             //scanf("%d%d",&x[i],&y[i]);
 78         scanf("%d",&d);
 79         double ans = 0;
 80          r1 = 2;
 81          l2 = 1;
 82         double tmp = 0;
 83         while(l2 < n && x[l2+1] < 2*d)l2++;
 84         for(int i = r1;i < l2;i++)
 85         {
 86             tmp += (double)(x[i+1] - x[i])*(y[i] + y[i+1])/2;
 87         }
 88         if(l2  == 1)
 89         {
 90             tmp -= (double)(x[2] - x[1])*(y[2] + y[1])/2;
 91         }
 92         x[n+1] = x[n];
 93         y[n+1] = y[n];
 94         nowx = 0;
 95         //printf("%d %d\n",r1,l2);
 96         while(l2 < n && r1 <= n)
 97         {
 98             int p1 = x[r1];
 99             int p2 = x[l2 + 1] - 2*d;
100             if(p1 < p2)
101                 nextx = p1;
102             else nextx = p2;
103             nextx = min(L- 2*d,nextx);
104             //printf("%d %d\n",nowx,nextx);
105             ans = max(ans,tmp + solve());
106             if(p1 < p2)
107             {
108                 nowx = p1;
109                 if(r1 < n)tmp -= (double)(x[r1+1] - x[r1])*(y[r1+1] + y[r1] )/2;
110                 r1++;
111             }
112             else
113             {
114                 nowx = p2;
115                 tmp += (double)(x[l2+1] - x[l2])*(y[l2+1] + y[l2])/2;
116                 l2++;
117             }
118         }
119         printf("%.3lf\n",ans/2/d);
120     }
121     return 0;
122 }

 

 

 

 

 

 

 

 改成了O(n)的解法。

因为三分的那个函数是二次函数。

找最大值,只要找两个端点和对称轴处就足够了!

还是太弱,现场没有想到这个优化,改起来很容易的。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <map>
  7 #include <set>
  8 #include <vector>
  9 #include <string>
 10 #include <math.h>
 11 using namespace std;
 12 const int MAXN = 200010;
 13 int x[MAXN],y[MAXN];
 14 int d;
 15 int n;
 16 int L;
 17 int nowx ;
 18 int nextx;
 19 int r1,l2;
 20 const double eps = 1e-8;
 21 double solve()
 22 {
 23     double left = nowx,right = nextx;
 24     //求出二次函数的a,b,c系数
 25     double tmp11 = x[r1];
 26     double tmp12 = -1;
 27     double tmp13 = (double)y[r1] - (double)x[r1]*(y[r1-1] - y[r1])/(x[r1-1] - x[r1])/2;
 28     double tmp14 = (double)(y[r1-1] - y[r1])/(x[r1-1] - x[r1])/2;
 29     double tmp21 = 2*d - x[l2];
 30     double tmp22 = 1;
 31     double tmp23 = y[l2] + (double)(2*d - x[l2])*(y[l2+1] - y[l2])/(x[l2+1] - x[l2])/2;
 32     double tmp24 = (double)(y[l2+1] - y[l2])/(x[l2+1] - x[l2])/2;
 33     //函数Y = (tmp11 + tmp12 * x)*(tmp13 + tmp14 * x) + (tmp21 + tmp22 * x)*(tmp23 + tmp24*x)
 34     double a = tmp12 * tmp14 + tmp22 * tmp24;
 35     double b = tmp11 * tmp14 + tmp12 * tmp13 + tmp21 * tmp24 + tmp22 * tmp23;
 36     double c = tmp11 * tmp13 + tmp21 * tmp23;
 37 
 38     double x0 = -b /(2*a);//对称轴
 39     double ret = max(a*left*left + b*left + c,a*right *right + b * right + c);
 40     if(x0 >= left && x0 <= right)
 41         ret = max(ret,a * x0 * x0 + b*x0 + c);
 42     return ret;
 43 
 44     /*
 45     double ret1,ret2;
 46     for(int cc = 0;cc <= 30;cc++)
 47     {
 48         double mid = (left + right)/2;
 49         double midmid = (mid + right)/2;
 50         double h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (mid  - x[r1])/(x[r1-1] - x[r1]);
 51         double h2 = y[l2] + (double)(y[l2+1] - y[l2])*(mid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
 52         ret1 = (double)(x[r1] - mid)*(h1 + y[r1])/2 + (double)(mid + 2*d - x[l2])*(h2 + y[l2])/2;
 53         
 54          h1 = y[r1] + (double)(y[r1-1] - y[r1]) * (midmid  - x[r1])/(x[r1-1] - x[r1]);
 55          h2 = y[l2] + (double)(y[l2+1] - y[l2])*(midmid + 2*d - x[l2])/(x[l2 + 1] - x[l2]);
 56         ret2 = (double)(x[r1] - midmid)*(h1 + y[r1])/2 + (double)(midmid + 2*d - x[l2])*(h2 + y[l2])/2;
 57         if(ret1 < ret2)
 58             left = mid+eps;
 59         else right = midmid-eps;
 60     }
 61     return ret1;
 62     */
 63 }
 64 
 65 
 66 int input()
 67 {
 68     char ch;
 69     ch = getchar();
 70     while(ch < '0' || ch >'9')
 71     {
 72         ch = getchar();
 73     }
 74     int ret = 0;
 75     while(ch >= '0' && ch <= '9')
 76     {
 77         ret *= 10;
 78         ret += ch -'0';
 79         ch = getchar();
 80     }
 81     return ret;
 82 }
 83 
 84 int main()
 85 {
 86     //freopen("D.txt","r",stdin);
 87     //freopen("out.txt","w",stdout);
 88     int T;
 89     scanf("%d",&T);
 90     while(T--)
 91     {
 92         scanf("%d%d",&n,&L);
 93         for(int i = 1;i <= n;i++)
 94         {
 95             //x[i] = input();
 96             //y[i] = input();
 97             scanf("%d%d",&x[i],&y[i]);
 98         }
 99             //scanf("%d%d",&x[i],&y[i]);
100         scanf("%d",&d);
101         double ans = 0;
102          r1 = 2;
103          l2 = 1;
104         double tmp = 0;
105         while(l2 < n && x[l2+1] < 2*d)l2++;
106         for(int i = r1;i < l2;i++)
107         {
108             tmp += (double)(x[i+1] - x[i])*(y[i] + y[i+1])/2;
109         }
110         if(l2  == 1)
111         {
112             tmp -= (double)(x[2] - x[1])*(y[2] + y[1])/2;
113         }
114         x[n+1] = x[n];
115         y[n+1] = y[n];
116         nowx = 0;
117         //printf("%d %d\n",r1,l2);
118         while(l2 < n && r1 <= n)
119         {
120             int p1 = x[r1];
121             int p2 = x[l2 + 1] - 2*d;
122             if(p1 < p2)
123                 nextx = p1;
124             else nextx = p2;
125             nextx = min(L- 2*d,nextx);
126             //printf("%d %d\n",nowx,nextx);
127             ans = max(ans,tmp + solve());
128             if(p1 < p2)
129             {
130                 nowx = p1;
131                 if(r1 < n)tmp -= (double)(x[r1+1] - x[r1])*(y[r1+1] + y[r1] )/2;
132                 r1++;
133             }
134             else
135             {
136                 nowx = p2;
137                 tmp += (double)(x[l2+1] - x[l2])*(y[l2+1] + y[l2])/2;
138                 l2++;
139             }
140         }
141         printf("%.3lf\n",ans/2/d);
142     }
143     return 0;
144 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/p/3506410.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞