luogu 1169 棋盘制作(单调栈/悬线)

luogu 1169 棋盘制作(单调栈/悬线)

国际象棋是世界上最古老的博弈游戏之一,和中国的围棋、象棋以及日本的将棋同享盛名。据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳。而我们的主人公小Q,正是国际象棋的狂热爱好者。作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则。小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一。小Q想在这种纸中裁减一部分作为新棋盘,当然,他希望这个棋盘尽可能的大。不过小Q还没有决定是找一个正方形的棋盘还是一个矩形的棋盘(当然,不管哪种,棋盘必须都黑白相间,即相邻的格子不同色),所以他希望可以找到最大的正方形棋盘面积和最大的矩形棋盘面积,从而决定哪个更好一些。于是小Q找到了即将参加全国信息学竞赛的你,你能帮助他么?N, M ≤ 2000。

首先,一个是棋盘的矩阵,满足相邻两个元素颜色不同。假设左上角的(1,1)是白色的格子。那么易证,横纵坐标之和是偶数的格子是白色的,是奇数的各自是黑色的。所以逆向思维,只要把给定的矩阵,横纵坐标之和同模2的一种格子反色,问题就变成了求最大的同色矩阵和同色正方形。这是最大子矩阵问题。用单调栈可以做,不过比悬线法烦一些。下面我来介绍一下悬线法。

悬线就是一端贴着不可算入矩形的区域(墙壁)的线。首先,一个最大子矩阵中一定有悬线,不然这个矩阵是可以再扩张的。所以,我们只要枚举所有悬线即可。首先n^2预处理出每个点向上向下能扩展的最大距离。然后从左向右,从右向左分别枚举一遍所有悬线(横向的),找出最大值即可。详见代码。

还有,个人感觉这种题目的思路很重要,就是把求最优解,转化为求出每个元素作为基础的最优值,然后取最优值中的最优值作为答案。

#include <cstdio>
using namespace std;

const int maxn=2005, INF=1e9;\
typedef int inta2[maxn][maxn];

int n, m, ans1, ans2, begin, minup, mindown;
inta2 a, up, down;

int max(int x, int y){ return x<y?y:x; }
int min(int x, int y){ return x<y?x:y; }
int sqr(int x){ return x*x; }

int main(){
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; ++i) //转换棋盘
        for (int j=1; j<=m; ++j){
            scanf("%d", &a[i][j]);
            if (i&1) a[i][j]^=1;
            if (!(j&1)) a[i][j]^=1;
        }
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=m; ++j)
            up[i][j]=(a[i][j]==a[i-1][j]?
                up[i-1][j]+1:1);
    for (int i=n; i>0; --i)
        for (int j=1; j<=m; ++j)
            down[i][j]=(a[i][j]==a[i+1][j]?
                down[i+1][j]+1:1);
    //悬线法
    for (int color=0; color<=1; ++color)
    for (int i=1; i<=n; ++i){
        minup=mindown=INF; begin=1;
        for (int j=1; j<=m; ++j){
            if (a[i][j]!=color){
                minup=mindown=INF;
                begin=j+1; continue;
            }
            minup=min(minup, up[i][j]);
            mindown=min(mindown, down[i][j]);
            ans1=max(ans1, (minup+mindown-1)*(j-begin+1));
            ans2=max(ans2, sqr(min(minup+mindown-1, j-begin+1)));
        }
        minup=mindown=INF; begin=m;
        for (int j=m; j>0; --j){
            if (a[i][j]!=color){
                minup=mindown=INF;
                begin=j-1; continue;
            }
            minup=min(minup, up[i][j]);
            mindown=min(mindown, down[i][j]);
            ans1=max(ans1, (minup+mindown-1)*(begin-j+1));
            ans2=max(ans2, sqr(min(minup+mindown-1, begin-j+1)));
        }
    }
    printf("%d\n%d", ans2, ans1);
    return 0;
}

转载于:https://www.cnblogs.com/MyNameIsPc/p/8445729.html

基于径向基函数神经网络RBFNN的自适应滑模控制学习(Matlab代码实现)内容概要:本文介绍了基于径向基函数神经网络(RBFNN)的自适应滑模控制方法,并提供了相应的Matlab代码实现。该方法结合了RBF神经网络的非线性逼近能力和滑模控制的强鲁棒性,用于解决复杂系统的控制问题,尤其适用于存在不确定性和外部干扰的动态系统。文中详细阐述了控制算法的设计思路、RBFNN的结构与权重更新机制、滑模面的构建以及自适应律的推导过程,并通过Matlab仿真验证了所提方法的有效性和稳定性。此外,文档还列举了大量相关的科研方向和技术应用,涵盖智能优化算法、机器学习、电力系统、路径规划等多个领域,展示了该技术的广泛应用前景。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的研究生、科研人员及工程技术人员,特别是从事智能控制、非线性系统控制及相关领域的研究人员; 使用场景及目标:①学习和掌握RBF神经网络与滑模控制相结合的自适应控制策略设计方法;②应用于电机控制、机器人轨迹跟踪、电力电子系统等存在模型不确定性或外界扰动的实际控制系统中,提升控制精度与鲁棒性; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,深入理解算法实现细节,同时可参考文中提及的相关技术方向拓展研究思路,注重理论分析与仿真验证相结合。
由于给定引用中未涉及洛谷P1186题目的相关C++代码及具体信息,所以无法直接分析解决该题目的C++代码。不过可以从一般的解题思路来考虑分析此类问题。 ### 代码功能分析 通常对于洛谷上的题目代码,要分析其功能,需要从输入输出、数据结构使用、核心算法逻辑等方面入手。比如,代码从标准输入读取数据,可能使用数组、结构体等数据结构来存储数据,通过某种算法(如动态规划、贪心算法、搜索算法等)对数据进行处理,最后将结果输出到标准输出。 ### 优化建议 - **时间复杂度优化**:如果代码的时间复杂度较高,如$O(n^2)$甚至更高,可以考虑使用更高效的算法。例如,将暴力枚举算法优化为动态规划算法,或者使用数据结构(如线段树、树状数组等)来降低时间复杂度。 - **空间复杂度优化**:若代码使用了大量的内存,可以考虑使用滚动数组、压缩存储等方法来减少空间使用。 - **代码结构优化**:可以将代码拆分成多个函数,使代码结构更清晰,提高代码的可读性和可维护性。 ### 示例代码分析(以引用中的其他代码为例) 以下以引用[2]中的寻宝题代码为例进行分析: ```cpp #include<iostream> using namespace std; struct dl{ int a; bool b; }; struct dl mig[10005][1005]; int n,m,l,num=0; int main(){ cin>>n>>m; for(int i=0;i<n;i++)//输入每个房间的信息 for(int j=0;j<m;j++){ cin>>mig[i][j].b>>mig[i][j].a; } cin>>l; for(int i=0;i<n;i++){//在每一层里面找到进入下一层的房间 int t=0;//计数器 int j=l; num=(num+mig[i][l].a)%20123;//和 while(1){ if(mig[i][j].b) t++; if(t==mig[i][l].a) break;//注意j在不断变化 j++; if(j==m) j=0; } l=j; } cout<<num; return 0; } ``` #### 代码功能 - 定义了一个结构体`dl`,用于存储每个房间的两个信息:`b`(布尔类型)和`a`(整数类型)。 - 从标准输入读取楼层数`n`、每层的房间数`m`以及初始进入的房间编号`l`。 - 读取每个房间的信息并存储在二维数组`mig`中。 - 遍历每一层,在每一层中根据规则找到进入下一层的房间,同时累加每个房间的`a`值,并对结果取模20123。 - 最后输出累加结果。 #### 优化建议 - **代码可读性**:可以将查找进入下一层房间的逻辑封装成一个函数,使`main`函数更简洁。 - **边界条件检查**:可以添加对输入数据的边界条件检查,增强代码的健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值