题目链接:uva 1543 - Telescope
题目大意:按照逆时针的顺序给出单位圆上的点(按照百分比),然后给出k,要求选出k个点组成的多边形面积最大,输出最大值。
解题思路:一开始想错方向了,状态都想好了,但是不知怎么求面积,一直想着说一圆心和圆上两点去求面积,但是这样就有说圆形在多边形外部的可能。后来想到海伦公式,根据三条边的长度求面积,然后圆是个环状的。所以将dp数组放大一倍。dp[i][j][k]表示从第i个点到第j个点选k个点的最大面积(i,j必须选)
#include#include #include #include using namespace std; const int N = 50; const double pi = atan(1.0) * 4; int n, k; double dp[N][N][N]; double p[N], d[N][N], area[N][N][N]; inline double dis(int x, int y) { double a = p[y] - p[x]; if (a > 0.5) a = 1 - a; return 2 * sin(a*pi); } inline double getArea(double x, double y, double z) { double tmp = (x + y + z)/2; return sqrt(tmp * (tmp - x) * (tmp - y) * (tmp - z)); } void init () { for (int i = 0; i < n; i++) scanf("%lf", &p[i]); for (int i = 0; i < n; i++) for (int j = i+1; j < n; j++) d[i][j] = d[j][i] = dis(i, j); for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { for (int t = j+1; t < n; t++) { double tmp = getArea(d[i][j], d[j][t], d[t][i]); area[i][j][t] = area[i][t][j] = tmp; area[j][i][t] = area[j][t][i] = tmp; area[t][i][j] = area[t][j][i] = tmp; } } } } double solve () { memset(dp, 0, sizeof(dp)); for (int i = 3; i <= k; i++) { for (int x = 0; x < n; x++) { for (int y = x+1; y < n; y++) { for (int z = y+1; z < n; z++) dp[x][z][i] = max(dp[x][z][i], dp[x][y][i-1] + area[x][y][z]); } } } double ans = 0; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { ans = max(ans, dp[i][j][k]); } } return ans; } int main () { while (scanf("%d%d", &n, &k) == 2 && n + k) { init (); printf("%.6lf\n", solve()); } return 0; }