• ZOJ 1679 Telescope(区间DP变型题)


    题意:

    给定一个圆和圆周上面的 N 个点,选择其中的 M 个,按照在圆周上的顺序连成一个 M 边形,使得它的面积最大。

    (黑书 147 圆和多边形)

    思路:

    1. 我一开始尝试的是 dp[i, j] 表示前 i 边形在前 j 个点上的最大面积。想来想去,因为三角形的起点和终点无法固定,则要加强下命题;

    2. 对于此类循环类型的动态规划,一般想办法和区间 DP 挂上钩。dp[i, d, j] 表示以 i 点出发,且以 [i, i+d-1] 为区间,找到 j 个点的最大面积;

    3. 这样的话,枚举 i,输出 dp[i, N, M] 即可。但是仍然无法保证三角形的第三个点的位置。还需要再次加强命题;

    4. dp[i, d, j] 表示以 i 点出发,且以 [i, i+d-1] 为区间,以 i+d-1 点结束。找到 j 个点使面积最大的情况。问题变得明朗了;

    5. dp[i, d, j] = max(dp[i, d, j], dp[i, k, j-1] + s[i, i+k-1, i+d-1]); 最终时间复杂度被加强为 O(N * N * M * M);

     

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    
    const int MAXN = 41;
    const double PI = acos(-1.0);
    
    double p[MAXN], s[MAXN][MAXN][MAXN], dp[MAXN][MAXN][MAXN];
    
    class CVector {
    public:
        CVector(double _x, double _y) : x(_x), y(_y) {}
        double operator * (const CVector& other) const {
            return x * other.y - y * other.x;
        }
    private:
        double x, y;
    };
    
    void initdata(int n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    CVector v1(cos(p[i]*PI*2), sin(p[i]*PI*2));
                    CVector v2(cos(p[j]*PI*2), sin(p[j]*PI*2));
                    CVector v3(cos(p[k]*PI*2), sin(p[k]*PI*2));
                    s[i][j][k] = fabs((v1*v2 + v2*v3 + v3*v1) / 2);
                }
            }
        }
    }
    
    int main() {
        int N, M;
        while (scanf("%d%d", &N, &M) && N && M) {
            for (int i = 0; i < N; i++)
                scanf("%lf", &p[i]);
            initdata(N);
            for (int d = 0; d <= N; d++)
                for (int i = 0; i < N; i++)
                    for (int m = 0; m <= M; m++)
                        dp[i][d][m] = 0.0;
    
            for (int d = 3; d <= N; d++) {
                for (int i = 0; i < N; i++) {
                    for (int m = 3; m <= M && m <= d; m++)
                        for (int k = m-1; k <= d-1; k++) 
                            dp[i][d][m] = max(dp[i][d][m], dp[i][k][m-1] + s[i][(i+k-1)%N][(i+d-1)%N]);
                }
            }
            double ans = 0.0;
            for (int i = 0; i < N; i++)
                for (int d = M; d <= N; d++)
                    ans = max(ans, dp[i][d][M]);
            printf("%.6lf\n", ans);
        }
        return 0;
    }
  • 相关阅读:
    Linux(CentOS 7)搭建DHCP服务器实验
    Linux(CentOS 7)发布静态网站
    Linux(CentOS 7)搭建VSFTP服务器
    Linux(CentOS 7)搭建samba服务器搭建实验
    Linux(CentOS 7)软件的安装
    Linux(CentOS 7)服务于进程
    Linux磁盘配额
    Linux LVM逻辑卷管理
    Linux磁盘挂载
    Linux磁盘分区
  • 原文地址:https://www.cnblogs.com/kedebug/p/3007300.html
Copyright © 2020-2023  润新知