PAT T1023 The Best Polygon

先对所有点极角排序,再动态规划~

#include<bits/stdc++.h>
using namespace std;
const int maxn=1014;
struct node {
    double x,y,dx,dy;
    int id;
}Node[maxn];
double dp[400][400][20],x=0,y=0;
bool cmp (node a,node b) {
    return (a.x-x)*(b.y-y)<(a.y-y)*(b.x-x);
}
vector<int> ans,path[305][305];
double getArea (node a,node b,node c) {
    double x1=b.x-a.x;
    double y1=b.y-a.y;
    double x2=b.x-c.x;
    double y2=b.y-c.y;
    return abs(x1*y2-x2*y1)*0.5; 
} 
int main () {
    int n,m;
    scanf ("%d %d",&n,&m);
    for (int i=0;i<n;i++) {
        scanf ("%lf %lf",&Node[i].x,&Node[i].y);
        Node[i].id=i;
        x+=Node[i].x;
        y+=Node[i].y;
    }
    x/=n;
    y/=n;
    sort (Node,Node+n,cmp);//极角排序,让给出的点按顺时针排序 
    double Max=0;
    int ri,rj;
    for (int k=3;k<=m;k++) {
        for (int i=0;i<n;i++) {
            for (int j=n-1;j>=i+k-1;j--) {
                for (int l=j-1;l>=i+1;l--) {
                    //dp[i][j][k]表示第i到第j个点选取k个点的最大值 
                    double area=dp[i][l][k-1]+getArea(Node[i],Node[l],Node[j]);
                    //中间结点第i个点到第l个点,选取k-1个点,再加上一个新选取的三角形 
                    if (area>dp[i][j][k]) {
                        dp[i][j][k]=area;
                        path[i][j]=path[i][l];
                        path[i][j].push_back(l);
                        //保存每个区间的路径 
                        if (dp[i][j][k]>Max) {
                            Max=dp[i][j][k];//保存当前k边形的最大值 
                            ri=i;
                            rj=j;
                        }
                    }
                }
            }
        }
    }
    ans.push_back(Node[ri].id);
    ans.push_back(Node[rj].id);//将两个端点推入数组 
    for (int i=0;i<path[ri][rj].size();i++) 
    ans.push_back(Node[path[ri][rj][i]].id);
    sort (ans.begin(),ans.end());
    for (int i=ans.size()-1;i>=0;i--) {
        if (i!=ans.size()-1) printf (" ");
        printf ("%d",ans[i]);
    } 
    return 0;
}

 

posted @ 2020-02-14 21:39  zlc0405  阅读(210)  评论(0编辑  收藏  举报