1023 The Best Polygon (35 分)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38449464/article/details/88799579

1、Problem:

       https://pintia.cn/problem-sets/994805148990160896/problems/994805149061464064

2、tags:

       dp  极角排序

3、Mean:

       给出N个点,找n边形使其面积最大 6<=n<=10,  N<=300

4、Solution:

       因为最多就10边形,N总数也不是很大,可以暴力一些..

       最开始的想法是找到哪些点不要.就是找面积最小的三角形,然后一个个删掉.然后这个想法问题很多,比如三角形面积会有重叠,然后连在一起的删去时还要额外有一部分减掉巴拉巴拉

       后来看题解说dp. dp[i][j][k]表示 第i到第j选k个点的最大值. 感觉还是能做的.

       转移方程 dp[i][j][k] = max{dp[i][h][k-1] + S(i,h,j) }; h 相当于中间节点,暴力搜索上一层,都不带优化的

       然后路径用vector存,取的时候直接拿来,再加上h即可

       输出之前要把端点也放进去 (路径不含端点)

5、Mistakes:

       1.dp顺序反了.j应该从后往前遍历,因为会用到 pth[i][h] h<j,即前面的路径.和背包一个道理.

       2.极角排序,开始是用p[0]作为基准点拍,WA了.看了其他人代码 都是找中间点.试了一下Ok了..

6、Gains:

       极角排序用中间点 比较稳妥(虽然不知道为什么)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
    double x,y,dx,dy;
    int id;
}p[500];
double dp[400][400][15],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,pth[305][305];
double getS(node a,node b,node c){
	double x1=b.x-a.x,y1=b.y-a.y,x2=b.x-c.x,y2=b.y-c.y;
	return abs(x1*y2-x2*y1)*0.5;
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        scanf("%lf %lf",&p[i].x,&p[i].y),p[i].id=i;
		X+=p[i].x; Y+=p[i].y;
    }//一定要选用中心点极角排序
	X/=n; Y/=n;//一开始我用第一个点作为基准点排序,错两个test
    sort(p,p+n,cmp);//极角排序
	double M=0; int I,J;
	for(int k=3;k<=m;k++){
		for(int i=0;i<n;i++){//起点
			for(int j=n-1;j>=i+k-1;j--){//结束点 //倒着遍历 方便pth加入路径,不然会被修改
				for(int l=j-1;l>=i+1;l--){//l->中间点
					double S = dp[i][l][k-1]+getS(p[i],p[l],p[j]);
					if(S > dp[i][j][k]){
						dp[i][j][k] = S;	
						pth[i][j] = pth[i][l];//获取路径
						pth[i][j].push_back(l);//加入点l
						if(dp[i][j][k]>M) M=dp[i][j][k],I=i,J=j;//最大值所在路径
					}
				}
			}
		}
	}
	ans.push_back(p[I].id); ans.push_back(p[J].id);
	for(int i=0;i<pth[I][J].size();i++)
		ans.push_back(p[pth[I][J][i]].id);
    sort(ans.begin(),ans.end());
    for(int i=ans.size()-1;i>=0;i--)
        printf("%d%c",ans[i],i==0?'\n':' ');
}

猜你喜欢

转载自blog.csdn.net/qq_38449464/article/details/88799579
今日推荐