UVA 1331 Minimax Triangulation (dp)

题意:给一个m边形,将其分割成m-2个三角形,求使得最大的三角形的面积最小的分割方案中这个最大的三角形的面积是多少

分析:

本题和三角形剖分类似,设dp[i][j]为从点i到j中最大的三角形面积,可得状态转移方程

dp[i][j] = min(dp[i][j],max(area(i,j,k),max(dp[i][k],dp[k][j])))

在进行状态转移之前还需要判断是否这三个点能否构成三角形,即这个三角形中是否有其他的点

设三个点为a,b,c 那一个点为k,如果Sabk+Sack+Sbck  = Sabc 那么说明该点在此三角形内,再判断的时候要注意有精度误差。

最后要注意递推的方向,不能按照 i 或者 j 递增或递减的方向递推,要按照 j - i 递增的顺序递推,因为长区间的结果依赖于短区间

代码:

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <sstream>
#define ll long long
#define mod 1000000007
#define mod1 10001
#define mem(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn = 50 + 5 , inf = 0x3f3f3f3f ;
int x[maxn],y[maxn];
double dp[maxn][maxn];
int m;
double area(int a,int b,int c){//计算面积
     double s=(double)(1.0/2)*(x[a]*y[b]+x[b]*y[c]+x[c]*y[a]-x[a]*y[c]-x[b]*y[a]-x[c]*y[b]);
     return fabs(s);
}
bool can(int a,int b,int c){//判断三角形是否成立
    for(int i = 1 ; i <= m ; i ++ ){
        if(i==a||i==b||i==c) continue;
        double s = area(a,b,i) + area(a,c,i) + area(b,c,i) - area(a,b,c);
        if(fabs(s) < 0.01) return false;
    }
    return true;
}
main(){
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n;
    scanf("%d",&n);
    while(n--){
        mem(dp);
        scanf("%d",&m);
        for(int i = 1 ; i <= m ; i ++ )
            scanf("%d %d",&x[i],&y[i]);
        for(int i = m-2 ; i >=1 ; i -- ){//注意递推方向
            for(int j = i + 2 ; j <= m ; j ++ ){
                dp[i][j] = inf;
                for(int k = i+1 ; k < j ; k ++ ){
                    if(can(i,j,k))
                    dp[i][j] = min(dp[i][j],max(area(i,j,k),max(dp[i][k],dp[k][j])));
                }
            }
        }
        printf("%.1f\n",dp[1][m]);
    }
}

猜你喜欢

转载自blog.csdn.net/insist_77/article/details/80880784