HUOJ-10857 最大的面积 凸包+DP

  题目链接:http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10857&courseid=55

  比赛的时候把题目看成取恰好K个点了,,,悲剧。。然后按照正确的题意的话,是比较好做的,求个凸包,然后DP就可以了,f[i][j][k]表示第 i 个点到第 j 点选择k个点的多边形的最大面积,那么f[i][j][k]=Max{ f[i][j][k], f[i][y][k-1]+area(p[i],p[y],p[j]) }就可以了。。

  这题相当悲剧,题目的数据范围描述错了,k应该是小于等于30,因为题目sb,看了一晚上的代码= =!

  1 //STATUS:C++_AC_0MS_1284KB
  2 #include <functional>
  3 #include <algorithm>
  4 #include <iostream>
  5 //#include <ext/rope>
  6 #include <fstream>
  7 #include <sstream>
  8 #include <iomanip>
  9 #include <numeric>
 10 #include <cstring>
 11 #include <cassert>
 12 #include <cstdio>
 13 #include <string>
 14 #include <vector>
 15 #include <bitset>
 16 #include <queue>
 17 #include <stack>
 18 #include <cmath>
 19 #include <ctime>
 20 #include <list>
 21 #include <set>
 22 #include <map>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,102400000")
 25 //using namespace __gnu_cxx;
 26 //define
 27 #define pii pair<int,int>
 28 #define mem(a,b) memset(a,b,sizeof(a))
 29 #define lson l,mid,rt<<1
 30 #define rson mid+1,r,rt<<1|1
 31 #define PI acos(-1.0)
 32 //typedef
 33 typedef long long LL;
 34 typedef unsigned long long ULL;
 35 //const
 36 const int N=60;
 37 const int INF=0x3f3f3f3f;
 38 const int MOD=1000000007,STA=8000010;
 39 const LL LNF=1LL<<60;
 40 const double EPS=1e-8;
 41 const double OO=1e60;
 42 const int dx[4]= {-1,0,1,0};
 43 const int dy[4]= {0,1,0,-1};
 44 const int day[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
 45 //Daily Use ...
 46 //End
 47 
 48 struct point{
 49     double x, y;
 50 }p[N],res[N];
 51 
 52 double f[N][N];
 53 int T,n,k;
 54 
 55 bool mult(point sp, point ep, point op)
 56 {
 57     return (sp.x - op.x) * (ep.y - op.y)>= (ep.x - op.x) * (sp.y - op.y);
 58 }
 59 
 60 bool operator < (const point &l, const point &r)
 61 {
 62     return l.y < r.y || (l.y == r.y && l.x < r.x);
 63 }
 64 
 65 int graham(point pnt[], int n, point res[])
 66 {
 67     int i, len, k = 0, top = 1;
 68     sort(pnt, pnt + n);
 69     if (n == 0) return 0;
 70     res[0] = pnt[0];
 71     if (n == 1) return 1;
 72     res[1] = pnt[1];
 73     if (n == 2) return 2;
 74     res[2] = pnt[2];
 75     for (i = 2; i < n; i++){
 76         while (top && mult(pnt[i], res[top], res[top-1]))top--;
 77         res[++top] = pnt[i];
 78     }
 79     len = top;
 80     res[++top] = pnt[n - 2];
 81     for (i = n - 3; i >= 0; i--){
 82         while (top!=len && mult(pnt[i], res[top], res[top-1])) top--;
 83         res[++top] = pnt[i];
 84     }
 85     return top; // 返回凸包中点的个数
 86 }
 87 
 88 double arear(point& a,point& b,point& c)
 89 {
 90     double ret=0;
 91     ret+=a.x*b.y-a.y*b.x;
 92     ret+=b.x*c.y-b.y*c.x;
 93     ret+=c.x*a.y-c.y*a.x;
 94     return ret/2;
 95 }
 96 
 97 int main()
 98 {
 99  //   freopen("in.txt","r",stdin);
100     int i,j,x,y,cnt;
101     double ans;
102     scanf("%d",&T);
103     while(T--)
104     {
105         scanf("%d%d",&n,&k);
106         for(i=0; i<n; i++){
107             scanf("%lf%lf",&p[i].x,&p[i].y);
108         }
109         cnt=graham(p,n,res);
110         if(cnt<=2 || k<=2){
111             printf("0.00\n");
112             continue;
113         }
114         if(cnt<=k){
115             double sum=0;
116             for(i=0;i<cnt;i++)
117                 sum+=res[i].x*res[(i+1)%cnt].y-res[i].y*res[(i+1)%cnt].x;
118             printf("%.2lf\n",sum/=2);
119             continue;
120         }
121         ans=0;
122         int m=cnt;
123         while(m--){
124             mem(f,0);
125             point t=res[0];
126             for(j=0;j<cnt-1;j++)res[j]=res[j+1];
127             res[j]=t;
128             for(j=2;j<cnt;j++){
129                 for(x=3;x<=j+1 && x<=k;x++){
130                     for(y=x-2;y<j;y++){
131                         f[j][x]=max(f[j][x],f[y][x-1]+arear(res[0],res[y],res[j]));
132                     }
133                 }
134                 ans=max(ans,f[j][k]);
135             }
136         }
137 
138         printf("%.2lf\n",ans);
139     }
140     return 0;
141 }

 

转载于:https://www.cnblogs.com/zhsl/p/3309065.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值