• 洛谷P1169 [ZJOI2007]棋盘制作 悬线法 动态规划


    P1169 [ZJOI2007]棋盘制作

     (逼着自己做DP

    题意:

      给定一个包含0,1的矩阵,求出一个面积最大的正方形矩阵和长方形矩阵,要求矩阵中相邻两个的值不同。

    思路:

      悬线法。

      用途:

        解决给定矩阵中满足条件的最大子矩阵

      做法:

        用一条线(横竖貌似都行)左右移动直到不满足约束条件或者到达边界

      定义几个东西:

        left[i][j]left[i][j]:代表从(i,j)(i,j)能到达的最左位置

        right[i][j]right[i][j]:代表从(i,j)(i,j)能到达的最右位置

        up[i][j]up[i][j]:代表从(i,j)(i,j)向上扩展最长长度.

      递推公式:

        left[i][j]=max(left[i][j],left[i-1][j]left[i][j]=max(left[i][j],left[i1][j]

        right[i][j]=min(right[i][j],right[i-1][j]right[i][j]=min(right[i][j],right[i1][j]

      至于为什么递推公式中考虑上一层的情况?

        是因为up数组的定义,up数组代表向上扩展最长长度, 所以需要考虑上一层的情况.

    #include <algorithm>
    #include  <iterator>
    #include  <iostream>
    #include   <cstring>
    #include   <cstdlib>
    #include   <iomanip>
    #include    <bitset>
    #include    <cctype>
    #include    <cstdio>
    #include    <string>
    #include    <vector>
    #include     <stack>
    #include     <cmath>
    #include     <queue>
    #include      <list>
    #include       <map>
    #include       <set>
    #include   <cassert>
    
    using namespace std;
    #define lson (l , mid , rt << 1)
    #define rson (mid + 1 , r , rt << 1 | 1)
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define pb push_back
    #define pq priority_queue
    
    
    
    typedef long long ll;
    typedef unsigned long long ull;
    //typedef __int128 bll;
    typedef pair<ll ,ll > pll;
    typedef pair<int ,int > pii;
    typedef pair<int,pii> p3;
    
    //priority_queue<int> q;//这是一个大根堆q
    //priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
    #define fi first
    #define se second
    //#define endl '
    '
    
    #define OKC ios::sync_with_stdio(false);cin.tie(0)
    #define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
    #define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
    #define max3(a,b,c) max(max(a,b), c);
    #define min3(a,b,c) min(min(a,b), c);
    //priority_queue<int ,vector<int>, greater<int> >que;
    
    const ll mos = 0x7FFFFFFF;  //2147483647
    const ll nmos = 0x80000000;  //-2147483648
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f; //18
    const int mod = 1e9+7;
    const double esp = 1e-8;
    const double PI=acos(-1.0);
    const double PHI=0.61803399;    //黄金分割点
    const double tPHI=0.38196601;
    
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    
    
    /*-----------------------showtime----------------------*/
                const int maxn = 2009;
                int mp[maxn][maxn];
                int lef[maxn][maxn],righ[maxn][maxn],up[maxn][maxn];
    int main(){ 
                int n,m;
                scanf("%d%d", &n, &m);
                for(int i=1; i<=n; i++){
                    for(int j=1; j<=m; j++) {
                        scanf("%d", &mp[i][j]);
                    }
                }
    
                for(int i=1; i<=n; i++){
                    for(int j=1; j<=m; j++){
                        lef[i][j] = j;
                        if(j>1 && mp[i][j] != mp[i][j-1]) lef[i][j] = lef[i][j-1];
                        up[i][j] = 1;
                    }
                }
    
                for(int i=1; i<=n; i++){
                    for(int j=m; j>=1; j--){
                        righ[i][j] = j;
                        if(j < m && mp[i][j] != mp[i][j+1]) righ[i][j] = righ[i][j+1];
                    }
                }
                int ans1 = 1, ans2 = 1;
                for(int i=2; i<=n; i++){
                    for(int j=1; j<=m; j++){
                        if(mp[i][j] != mp[i-1][j]){
                            lef[i][j] = max(lef[i][j] , lef[i-1][j]);
                            righ[i][j] = min(righ[i][j], righ[i-1][j]);
                            up[i][j] = up[i-1][j] + 1;
                        }
    
                        int a = righ[i][j] - lef[i][j] + 1;
                        int b = up[i][j];
                        // cout<<a<<" "<<b<<endl;
                        ans2 = max(a * b, ans2);
    
                        int t = min(a, b);
                        ans1 = max(t * t, ans1);
                    }
                }
                printf("%d
    %d
    ", ans1, ans2);
                return 0;
    }
  • 相关阅读:
    使用Ansible连接AWS EC2
    centos7 常用工具包安装
    基于redis的分布式ID生成器
    使用Docker的macvlan为容器提供桥接网络及跨主机通讯
    小程序使用腾讯视频
    切换 Python2 Python3
    PHP字符串替换
    小程序常用操作,if,for,跳转,弹出提示
    小程序订单核销的思路
    PHP 批量删除的实现
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/10285414.html
Copyright © 2020-2023  润新知