zoukankan      html  css  js  c++  java
  • B1047 理想的正方形 RMQ

    大家吸取我的教训,想好再写。我码了好长时间,最后发现算法处理的是另一个问题,我处理的是正方形情况的,才能用我优化之后的记忆化搜索,然而矩形就凉了。

    先看一下题吧:

    Description
    
      有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
    的差最小。
    Input
    
      第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
    行相邻两数之间用一空格分隔。
    100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000
    Output
    
      仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
    Sample Input
    5 4 2
    
    1 2 5 6
    
    0 17 16 0
    
    16 17 2 1
    
    2 10 2 1
    
    1 2 2 2
    Sample Output
    1
    HINT
    
    Source

    我的反面教材代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define lv(i,a,n) for(int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    int a,b,n;
    int p[1010][1010];
    int f[1010][1010][15][3];
    int l[15];
    void dfs(int o,int x1,int y1,int x2,int y2)
    {
        if(f[x1][y1][o][1] != -1)
            return;
        if(x1 == x2 && y1 == y2)
        {
            f[x1][y1][o][1] = p[x1][y1];
            f[x1][y1][o][0] = p[x1][y1];
            return;
        }
        int minn = INF;
        int maxn = 0;
        dfs(o + 1,x1,y1,x1 + l[o],y1 + l[o]);
        dfs(o + 1,a - l[o],y1,a,y1 + l[o]);
        dfs(o + 1,x1,b - l[o],x1 + l[o],b);
        dfs(o + 1,a - l[o],b - l[o],a,b); 
    //    printf("%d %d %d %d
    ",a - l[o],b - l[o],a,b);
        maxn = max(maxn,f[x1][y1][o + 1][1]);
        minn = min(minn,f[x1][y1][o + 1][0]);
        maxn = max(maxn,f[a - l[o]][y1][o + 1][1]);
        minn = min(minn,f[a - l[o]][y1][o + 1][0]);
        maxn = max(maxn,f[x1][b - l[o]][o + 1][1]);
        minn = min(minn,f[x1][b - l[0]][o + 1][0]);
        maxn = max(maxn,f[a - l[o]][b - l[o]][o + 1][1]);
        minn = min(minn,f[a - l[o]][b - l[o]][o + 1][0]);
        f[x1][y1][o][1] = maxn;
        f[x1][y1][o][0] = minn;
        return;
    }
    int main()
    {
        memset(f,-1,sizeof(f));
        read(a);read(b);read(n);
        duke(i,1,a)
        {
            duke(j,1,b)
                read(p[i][j]);
        }
        int k = n,len = 0;
        while(k > 1)
        {
            k = ceil(k / 2);
            l[++len] = k;
    //        cout<<k<<endl; 
        }
        duke(i,1,a - n)
            duke(j,1,b - n)
                dfs(1,i,j,i + n,j + n);
        printf("%d %d
    ",f[1][1][1][1],f[1][1][1][0]);
        return 0;
    }
    /*
    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    */

    然后就凉了,懒得写了,用二维的RMQ搞一下,抄了个比较清晰的代码。。。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int INF = 1000000000;
    const int maxm = 1000 + 100;
    const int maxn = 100 + 10;
    const int maxlog = 10;
    
    int a, b, n;
    int logn;
    int grid[maxm][maxm];
    int maxv[maxm][maxm], minv[maxm][maxm];
    
    int query (int x, int y)
    {
        int _max = 0, _min = 0;
        _max = max(maxv[x][y], max(maxv[x+n-(1<<logn)][y+n-(1<<logn)], max(maxv[x+n-(1<<logn)][y], maxv[x][y+n-(1<<logn)])));
        _min = min(minv[x][y], min(minv[x+n-(1<<logn)][y+n-(1<<logn)], min(minv[x+n-(1<<logn)][y], minv[x][y+n-(1<<logn)])));
        return _max - _min;
    }
    
    int main ()
    {
    //    freopen("in.txt", "r", stdin);
        cin >> a >> b >> n;
        for (int i = 0; i < a; i++)
            for (int j = 0; j < b; j++)
            {
                scanf("%d", &grid[i][j]);
                maxv[i][j] = minv[i][j] = grid[i][j];
            }
    
        for (logn = 0; ((1<<(logn+1)) <= n); logn++);
        for (int k = 0; k < logn; k++)
            for (int i = 0; i+(1<<k) < a; i++)
                for (int j = 0; j+(1<<k) < b; j++)
                {
                    maxv[i][j] = max(maxv[i][j], max(maxv[i+(1<<k)][j+(1<<k)], max(maxv[i+(1<<k)][j], maxv[i][j+(1<<k)])));
                    minv[i][j] = min(minv[i][j], min(minv[i+(1<<k)][j+(1<<k)], min(minv[i+(1<<k)][j], minv[i][j+(1<<k)])));
                }
    
        int ans = INF;
        for (int i = 0; i <= a-n; i++)
            for (int j = 0; j <= b-n; j++)
                ans = min(ans, query(i, j));
    
        cout << ans;
        return 0;
    }

    唉,后悔啊。。。

  • 相关阅读:
    微信小程序---app.json中设置背景色不生效解决办法
    给网站设置ICO图标
    ajax事件(五)
    ajax关于主流中的异类:应对Opera(四)
    dashboard
    tomcat 清理日志
    jQuery datatable
    php wampserver 80 端口无法开启的解决方法
    mysql 行列转换
    jQuery-2.1.4.min.js:4 Uncaught TypeError: Illegal invocation
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9515034.html
Copyright © 2011-2022 走看看