zoukankan      html  css  js  c++  java
  • 悬线法

    悬线法用于n*m复杂度找矩阵的最优解。

    用l[i][j]表示i,j合法的情况下左边能延伸的坐标,r[i][j]是在右边能延伸的坐标

    up[i][j]是能向上延长的长度;

    l,r数组是坐标,up是长度

    模板题:P1169 [ZJOI2007]棋盘制作

    题意:给你个n*m矩阵,让你求最大01相间正方形和长方形矩阵。01相间就是相邻两个格子不一样。

    这个就是标准的悬线法,求出来以上的数组后,然后以每个i,j为边界,统计答案。

    x = r[i][j] - l[i][j] + 1。 这个就是底边。

    y = up[i][j]。这个就是宽。

    正方形就得取边短的的那个,min(x,y)*min(x,y)。长方形直接x*y。

    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define met(a, b) memset(a, b, sizeof(a))
    #define rep(i, a, b) for(int i = a; i <= b; i++)
    #define bep(i, a, b) for(int i = a; i >= b; i--)
    #define pb push_back
    #define mp make_pair
    #define debug cout << "KKK" << endl
    #define ls num*2
    #define rs num*2+1
    #define re return
    using namespace std;
    const ll mod = 998244353;
    const double PI = acos(-1);
    const ll INF = 2e18+1;
    const int inf = 1e9 + 15;
    const double eps = 1e-7;
    const int maxn = 2e3 + 5;
    int l[maxn][maxn], r[maxn][maxn], up[maxn][maxn];
    int ma[maxn][maxn];
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);    cout.tie(0);
        int n, m; cin >> n >> m;
        rep(i, 1, n){
            rep(j, 1, m){
                cin >> ma[i][j];
                l[i][j] = r[i][j] = j;
                up[i][j] = 1;
            }
        }
        rep(i, 1, n){
            rep(j, 2, m) if(ma[i][j] + ma[i][j-1] == 1) l[i][j] = l[i][j-1];
            bep(j, m-1, 1) if(ma[i][j] + ma[i][j+1] == 1) r[i][j] = r[i][j+1];
        }
        int ans1 = 0, ans2 = 0;
        rep(i, 1, n){
            rep(j, 1, m){
                if(i > 1 && ma[i][j] + ma[i-1][j] == 1){
                    up[i][j] = up[i-1][j] + 1;
                    l[i][j] = max(l[i-1][j], l[i][j]);  // 因为是左边能到达的坐标,max越大表示离i越近
                    r[i][j] = min(r[i-1][j], r[i][j]);  // 同上,min越小表示离i越近。
                }
                int x = r[i][j] - l[i][j] + 1;
                int y = min(x, up[i][j]);
                ans1 = max(ans1, y*y);
                ans2 = max(ans2, x*up[i][j]);
            }
        }
        cout << ans1 << '
    ' << ans2 << endl;
        re 0;
    }
  • 相关阅读:
    今日SGU 5.2
    奇异值分解(SVD)小结
    计蒜客16495 Truefriend(fwt)
    计蒜客16492 building(二分线段树/分块)
    hihocoder 1323 回文字符串(字符串+dp)
    hihocoder 1320 压缩字符串(字符串+dp)
    hdu6121 build a tree(树)
    hdu6103 Kirinriki(trick+字符串)
    hdu6097 Mindis(几何)
    hdu 6057 Kanade's convolution(子集卷积)
  • 原文地址:https://www.cnblogs.com/philo-zhou/p/12926263.html
Copyright © 2011-2022 走看看