UVa 1331

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;

const double INF=0x3f3f3f3f;
const int maxn=1000;
const double esp=1e-6;
int n,m;

struct point
{
    double x;double y;
}d[maxn];
double dp[maxn][maxn];

double area(point a,point b,point c)//平面解析几何里有公式,按照A,B,C的逆时针顺序写,依照行列式的方式可以得到该公式
{
    return fabs((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y)) / 2.0 ;
}

bool judge(int a,int b,int c)//判断如果是所圈出的三角形的一条边在凹多边形的外面了,就取消。
{
 for(int i=1;i<=m;i++)
 {
     if(i==a||i==b||i==c) continue;
     double s=area(d[i],d[a],d[b])+area(d[i],d[b],d[c])+area(d[i],d[a],d[c]);
     if(fabs(s-area(d[a],d[b],d[c]))<esp) return true;
 }
 return false;
}

int main()
{
   scanf("%d",&n);
    while(n--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%lf%lf",&d[i].x,&d[i].y);
        }
        for(int p=2;p<m;p++)//三角形以2为起步长度差,因为是三个顶点
        {
            for(int l=1;l+p<=m;l++)//依然按照短区间先算的原则再算长区间的原则进行计算
            {
                dp[l][l+p]=INF;
                for(int k=l+1;k<l+p;k++)
                {
                    if(judge(l,k,l+p))
                    {
                        continue;
                    }
                    dp[l][l+p]=min(dp[l][l+p],max(area(d[l],d[k],d[l+p]),max(dp[l][k],dp[k][l+p])));//最大三角形面积最小的三角剖分
                }
            }
        }
        printf("%.1f\n",dp[1][m]);
    }

    return 0;
}
这种矩阵连乘和三角剖分的问题都是这样的格式,都是三个循环为大格式,第一层为长度差,决定了区间的长短,然后就是 枚举长度和左边界始点,那么根据长度和左边界点就可以知道右边界点,然后枚举左边界和右边界中间的点k,dp[i][j] = min(dp[i][j], max(max(dp[i][k], dp[k][j]), Area(i, k, j)).但是有一个问题,即i,k,j三点围成的三角形是否符合要求,判断的条件即为是否存在除i,k,j三点外的一点位于三角形中,有面积法判断。   稍微难一些的就是这个状态转移方程要理解好怎么弄出来的,接下来的循环要写好。这个题目还有点难度的就是求面积的公式的应用,这个在平面解析几何里是有的,这个在大一解析几何里有学过的,还有就是判断那些不符合的三角形的judge的函数的编写,也就是i-j是不是对角线的判断。难点就这么几个。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值