最优子结构 - 三角剖分 uva 1331 Minimax Triangulation

本文探讨了如何通过优化策略来划分由n个点组成的多边形为n-2个三角形,目标是最小化最大三角形的面积。采用动态规划的方法进行求解,并考虑了确保三角形合法性的条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意大概:

给你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]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值