紫书 例题 9-11 UVa 1331 (最优三角形剖分)
设置f(i, j)为点i, i + 1 ……j所组成的多边形。
那么可以枚举中间点k, 得f(i, j) = min{s(i, j, k), f(i, k), f(k, j) | i < k < j}
当i + 1 == j,即i与j相邻的时候,f(i, j) = 0
在枚举三角形的时候,如果有点在多边形内,则要排除,因为这一部分包括了
多边形以外的面积。
同时知道三点坐标求面积用到了叉积的公式,要学习学习
fabs((x[b] - x[a]) * (y[c] - y[a]) - (x[c] - x[a]) * (y[b] - y[a])) / 2.0;
b a c a, c a b a, 可以这么记住
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;
const int MAXN = 55;
const double EPS = 1e-6;
double x[MAXN], y[MAXN], f[MAXN][MAXN];
int n;
inline double area(int a, int b, int c)
{
return fabs((x[b] - x[a]) * (y[c] - y[a]) - (x[c] - x[a]) * (y[b] - y[a])) / 2.0;
}
bool judge(int a, int b, int c)
{
REP(i, 0, n)
{
if(i == a || i == b || i == c) continue;
if(fabs(area(i, a, b) + area(i, b, c) + area(i, a, c) - area(a, b, c)) < EPS)
return false;
}
return true;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
REP(i, 0, n) scanf("%lf%lf", &x[i], &y[i]);
for(int i = n - 1; i >= 0; i--)
REP(j, i + 1, n)
{
if(j == i + 1) { f[i][j] = 0.0; continue; }
f[i][j] = 1e9;
REP(k, i + 1, j)
if(judge(i, j, k))
f[i][j] = fmin(f[i][j], fmax(area(i, j, k), fmax(f[i][k], f[k][j])));
}
printf("%.1lf\n", f[0][n-1]);
}
return 0;
}