题意大概:
给你n给点组成的多边形,连接对角线形成 n-2个三角形,问你最优策略使得 所形成的最大的三角形最小;
思路分析:
d(i,j)表示在点 i 到点 j 这一串点所构成的的多边形形成的最大的三角形最小;
当 i + 2 == j 时 只有一个三角形可以返回面积
double Area(int i,int j,int k){
return fabs((x[i]-x[j])*(y[i]-y[k])-(x[i]-x[k])*(y[i]-y[j]))*0.5;
}
i+1 == j 时返回 0
其他情况
d(i,j)=min( d ( i , j ) , max ( Area ( i , j , k ) , max(d ( i , k ), d( k , j ) ) ) );
判断三角形内是否有其他的点。
如果存在其他的点构不成三角形。
bool check(int i,int j,int k){
double A = Area(i,j,k);
for(int a=1;a<=n;a++){
if(a==i||a==j||a==k)continue;
double tmp = Area(i,j,a)+Area(i,k,a)+Area(a,j,k);
if(fabs(tmp - A)<0.001)return 0;
}
return 1;
}
记忆话搜索求解:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<cmath>
using namespace std;
#define N 1005
#define inf 0x3f3f3f3f
#define eps 0.001
int n;
double d[N][N];
int x[N],y[N];
double Area(int i,int j,int k){
return fabs((x[i]-x[j])*(y[i]-y[k])-(x[i]-x[k])*(y[i]-y[j]))*0.5;
}
bool check(int i,int j,int k){
double A = Area(i,j,k);
for(int a=1;a<=n;a++){
if(a==i||a==j||a==k)continue;
double tmp = Area(i,j,a)+Area(i,k,a)+Area(a,j,k);
if(fabs(tmp - A)<0.001)return 0;
}
return 1;
}
double dp(int i,int j){
double &t = d[i][j];
if(t>eps)return t;
if(j-i == 2){t = Area(i,i+1,j);return t;}
if(j-i == 1){t = 0;return 0;}
t = inf;
for(int k=i+1;k<j;k++){
if(check(i,j,k))
t = min(t,max(Area(i,j,k),max(dp(i,k),dp(k,j))));
}
return t;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(d,-1,sizeof(d));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x[i],&y[i]);
}
printf("%.1f\n",dp(1,n));
}
}
递推求解:
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 1005
#define inf 0x3f3f3f3f
struct Node
{
double x,y;
} a[N];
int n;
double d[N][N];
double Area(int i,int j,int k){
return fabs(0.5*((a[j].x-a[i].x)*(a[k].y-a[i].y)-(a[k].x-a[i].x)*(a[j].y-a[i].y)));
}
bool check(int a,int b,int c){
for(int i=0;i<n;i++){
if(i == a||i == b||i == c)continue;
double dis = Area(a,b,i)+Area(a,c,i)+Area(b,c,i)-Area(a,b,c);
if(dis<0)dis=-dis;
if(dis<=0.001)return 0;
}
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lf%lf",&a[i].x,&a[i].y);
}
for(int i=n-1; i>=0; i--)
{
d[i][i+1]=0;
for(int j=i+2; j<n; j++)
{
d[i][j]=inf;
for(int k=i+1; k<j; k++)
{
if(check(i,j,k))
d[i][j]=min(d[i][j],max(Area(i,j,k),max(d[i][k],d[k][j])));
}
}
}
printf("%.1f\n",d[0][n-1]);
}
}