zoukankan      html  css  js  c++  java
  • 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也想不到, 有时候真的感觉自己白学了一年......但是还是得接着学啊!

  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7278720.html
Copyright © 2011-2022 走看看