• UVA 1331 Minimax Triangulation DP, 三角剖分


      题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4077

      题目大意: 给出一个多边形, 输出三角剖分最大三角形最小化的最大三角形面积

      解题思路: 最大值最小化啊......猛然想到了二分, 但是这个是DP专题啊......d(i, j)表示多边形i ~ j的最优解, DP转移方程就是dp(i, j) = min(dp(i, j), max(dp(i, k), dp(k, j), get_Area(i, j, k)))

        下标是可以循环的, 我们先枚举长度, 再枚举左端点,然后再枚举中的点。有个trick, 如果是三个点组成的三角形有内点的话, 这三个点组成的三角形面积不算。 画图就知道了。

      代码:

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    using namespace std;
    
    struct Node {
        double x, y;
    };
    Node a[55];
    double d[55][55]; // d[i][j] z
    const int INF = 0x3fffffff;
    int m;
    const double eps = 1e-9;
    
    double area( int i, int j, int k ) {
        return 0.5 * abs(a[i].x*(a[j].y-a[k].y)+a[j].x*(a[k].y-a[i].y)+a[k].x*(a[i].y-a[j].y));
    }
    
    int judge( int p, int q, int r ) { // p, q, r组成的三角形无内点
        double cur = area(p, q, r);
        for( int i = 0; i < m; i++ ) {
            if( i == p || i == q || i == r ) continue;
            double temp = area(p, q, i) + area(q, r, i) + area(p, r, i);
            if( fabs(temp-cur) < eps ) return 0;
        }
        return 1;
    }
    
    int main() {
        int T;
        scanf( "%d", &T );
        while( T-- ) {
            memset(a, 0, sizeof(a));
            scanf( "%d", &m );
            for( int i = 0; i < m; i++ ) {
                scanf( "%lf%lf", &a[i].x, &a[i].y );
            }
            for( int i = 0; i < m; i++ ) {
                for( int j = 0; j < m; j++ ) {
                    if( i == 0 || i == 1 ) d[j][(j+i)%m] = 0.;
                    else if( i == 2 ) d[j][(j+i)%m] = area(j, (j+1)%m, (j+2)%m);
                    else d[j][(j+i)%m] = INF;
                }
            }
            for( int k = 3; k < m; k++ ) {
                for( int i = 0; i < m; i++ ) {
                    int t = (i+k)%m; // 右端点
    //                d[i][t] = INF;
                    for( int j = (i+1)%m; j != t; j = (j+1)%m ) {
                        if( judge(j, t, i) ) {
                            d[i][t] = min(d[i][t], max({d[i][j], d[j][t], area(i, j, t)}));
                        }
                    }
                }
            }
    //        for( int i = 0; i < m; i++ ) {
    //            for( int j = 0; j < m; j++ ) {
    //                printf( "%.1lf ", d[i][j] );
    //            }
    //            cout << endl;
    //        }
            printf( "%.1lf
    ", d[0][m-1] );
        }
        return 0;
    }
    View Code

      思考: 状态又想错了, 以后要是有点的话, 要考虑区间, 或者前i个点这种情况, 自己的心思不够缜密, 有好多漏解的情况, 还有Trick也想不到, 有时候真的感觉自己白学了一年......但是还是得接着学啊!

  • 相关阅读:
    linux NFS 的安装准备
    linux Sersync 参数说明
    linux测试 Sersync 是否正常
    linux开启 Sersync 守护进程进行数据同步
    linux 配置 Sersync
    Sersync 上配置 Sersync 服务
    linux Sersync 上配置客户端
    PowerDesigner一些小技巧
    C# System.Attribute(验证类)
    C#:实体类中做数据验证
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7278720.html
Copyright © 2020-2023  润新知