zoukankan      html  css  js  c++  java
  • [HG]钻石游戏diamond 题解

    题面

    钻石游戏(diamond)

    问题描述:
    一个(M)(N)列的棋盘,里面放了(M imes N)个各种颜色的钻石。
    每一次你可以选择任意两个相邻的颜色不同的钻石,进行交换。两个格子相邻的定义是两个格子有一条公共边。
    每次交换的分值为通过这次交换后能够形成的最大矩形的面积,具体请见样例。
    跟传统的钻石游戏不太一样的是,交换后钻石不会消除。现在告诉你每一次操作,
    请输出每一次所能得到的分值。
    问题输入:
     第一行二个整数(M,N)
     接下来(M)(N)列,表示第(I)行第(J)列的钻石的颜色((1-9))
     第(M+2)行有一个正整数(P),表示钻石交换的次数。
     接下来(P)行,每行四个正整数(x1,y1,x2,y2)(1 leq x1,x2 leq M,1 leq y1,y2 leq N),表示交换((x1,y1))((x2,y2))的钻石。
     保证((x1,y1),(x2,y2))的颜色不相同,并且其必定相邻。
    问题输出:
    (P)行,输出每次交换得到的分值

    题解

    这道题目的主要失误在于对数据范围估计错误,其实暴力模拟加小优化后的最劣复杂度为(Theta(n^2 imes q))
    约为(2500)万,是可以通过的。
    这题的暴力很简单,对于每次交换,向外扩展,然后在从内至外枚举,
    然后在枚举内部继续往另一个方向扩展,即可计算矩形面积。
    稍加分情况讨论即可,代码稍长,但是基本可以复制

    代码

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    int read(){
        int x = 0; int zf = 1; char ch = ' ';
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    
    //define n the row number, m the col number. 
    
    int n, m;
    int _max;
    int mp[505][505];
    
    int getL(int x, int y, int val){
        int cnt = 0;
        for (int i = y; i && mp[x][i] == val && (y - i) <= _max; --i)
            ++cnt;
        return cnt;
    }
    
    int getR(int x, int y, int val){
        int cnt = 0;
        for (int i = y; i <= m && mp[x][i] == val && (i - y) <= _max; ++i)
            ++cnt;
        return cnt;
    }
    
    int getU(int x, int y, int val){
        int cnt = 0;
        for (int i = x; i && mp[i][y] == val && (x - i) <= _max; --i)
            ++cnt;
        return cnt;
    }
    
    int getD(int x, int y, int val){
        int cnt = 0;
        for (int i = x; i <= n && mp[i][y] == val && (i - x) <= _max; ++i)
            ++cnt;
        return cnt;
    }
    
    int main(){
        n = read(), m = read();
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                mp[i][j] = read();
        int p = read();
        while (p--){
            int x1 = read(), y1 = read(), x2 = read(), y2 = read();
            if (x1 == x2){
                if (y1 > y2)
                    swap(x1, x2), swap(y1, y2);
            }
            else if (x1 > x2)
                swap(x1, x2), swap(y1, y2);
            swap(mp[x1][y1], mp[x2][y2]);
            if (x1 == x2){
                int ans = 0;
                _max = 505; int upper = getL(x1, y1, mp[x1][y1]);
                int minu = 505, mind = 505;
                for (int i = 1; i <= upper; ++i){
                    int j = y1 - i + 1;
                    minu = min(minu, getU(x1, j, mp[x1][y1]));
                    mind = min(mind, getD(x1, j, mp[x1][y1]));
                    _max = min(_max, max(minu, mind));
                    if ((minu + mind - 1) * i > ans)
                        ans = (minu + mind - 1) * i;
                }
                minu = 505, mind = 505;
                _max = 505, upper = getR(x2, y2, mp[x2][y2]);
                for (int i = 1; i <= upper; ++i){
                    int j = y2 + i - 1;
                    minu = min(minu, getU(x2, j, mp[x2][y2]));
                    mind = min(mind, getD(x2, j, mp[x2][y2]));
                    _max = min(_max, max(minu, mind));
                    if ((minu + mind - 1) * i > ans)
                        ans = (minu + mind - 1) * i;
                }
                printf("%d
    ", ans);
            }
            else{
                int ans = 0;
                _max = 505; int upper = getU(x1, y1, mp[x1][y1]);
                int minl = 505, minr = 505;
                for (int i = 1; i <= upper; ++i){
                    int j = x1 - i + 1;
                    minl = min(minl, getL(j, y1, mp[x1][y1]));
                    minr = min(minr, getR(j, y1, mp[x1][y1]));
                    _max = min(_max, max(minl, minr));
                    if ((minl + minr - 1) * i > ans)
                        ans = (minl + minr - 1) * i;
                }
                minl = 505, minr = 505;
                _max = 505, upper = getD(x2, y2, mp[x2][y2]);
                for (int i = 1; i <= upper; ++i){
                    int j = x2 + i - 1;
                    minl = min(minl, getL(j, y2, mp[x2][y2]));
                    minr = min(minr, getR(j, y2, mp[x2][y2]));
                    _max = min(_max, max(minl, minr));
                    if ((minl + minr - 1) * i > ans)
                        ans = (minl + minr - 1) * i;
                }
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    C#操作Word打印
    判断文件名是否有效
    Windows系统下的程序开机自启
    Winform应用程序使用自定义的鼠标图片
    C# 操作网络适配器
    Runtime Error! R6025-pure virtual function call
    Winform中跨线程访问UI元素的方法
    C#自定义属性转换类---类型转换器
    获取计算机硬件信息
    获取程序集信息
  • 原文地址:https://www.cnblogs.com/linzhengmin/p/11102356.html
Copyright © 2011-2022 走看看