紫书 例题 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;
} 

猜你喜欢

转载自blog.csdn.net/qq_34416123/article/details/81431241
今日推荐