博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵
阅读量:5103 次
发布时间:2019-06-13

本文共 2361 字,大约阅读时间需要 7 分钟。

https://www.luogu.org/problemnew/show/P1169

 

第一次听说到这种dp的名称叫做悬线法,听起来好厉害

题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[2000][2000][2]维护这个位置向上向左扩充的矩阵最大长度之后n²扫一遍,但是写起来发现并不能有效的扩充,也就是状态转移方程很难写出来。

后来发现有一种奥妙重重的方法叫做悬线法,把我原本向左向上扩充的过程改为记录每一个点向左向右向上的最大长度,这些状态很显然可以通过扫一遍的方法求出来,然后对于每一个点,宽度就是l - r + 1,显然对于同一个合法区间内的点,他的left和right是相同的。

用自上而下的方法递推出到N这一行时这个点向上扩充的最大长度之后递推即可。

悬线法对一类限制下求子矩阵的问题很好用。

#include #include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;inline int read(){ int now=0;register char c=getchar();for(;!isdigit(c);c=getchar());for(;isdigit(c);now=now*10+c-'0',c=getchar());return now;}#define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--)#define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x)#define Sca2(x,y) scanf("%d%d",&x,&y)#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)#define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x)#define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();#define LL long long#define ULL unsigned long long #define mp make_pair#define PII pair
#define PIL pair
#define PLL pair
#define pb push_back#define fi first#define se second typedef vector
VI;const double eps = 1e-9;const int maxn = 2010;const int INF = 0x3f3f3f3f;const int mod = 1e9 + 7; int N,M,K;int Left[maxn][maxn],Right[maxn][maxn],up[maxn][maxn];int MAP[maxn][maxn];int main(){ Sca2(N,M); for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= M ; j ++){ Sca(MAP[i][j]); Left[i][j] = Right[i][j] = j; up[i][j] = 1; } } for(int i = 1; i <= N ; i ++){ for(int j = 2; j <= M ; j ++){ if(MAP[i][j] != MAP[i][j - 1]){ Left[i][j] = Left[i][j - 1]; } } for(int j = M - 1; j >= 1; j --){ if(MAP[i][j] != MAP[i][j + 1]){ Right[i][j] = Right[i][j + 1]; } } } int ans1 = 0,ans2 = 0; for(int i = 1; i <= N ; i ++){ for(int j = 1; j <= M ; j ++){ if(i > 1 && MAP[i][j] != MAP[i - 1][j]){ Left[i][j] = max(Left[i][j],Left[i - 1][j]); Right[i][j] = min(Right[i][j],Right[i - 1][j]); up[i][j] = up[i - 1][j] + 1; } int a = Right[i][j] - Left[i][j] + 1; int b = min(a,up[i][j]); ans1 = max(ans1,b * b); ans2 = max(ans2,a * up[i][j]); } } Pri(ans1); Pri(ans2); return 0;}

 

转载于:https://www.cnblogs.com/Hugh-Locke/p/10261871.html

你可能感兴趣的文章
python keyboard方法_【Python】对字典列表进行去重追加
查看>>
python 时序分析_【时序分割】2017KDD时序分割聚类TICC代码分析
查看>>
java版flashplayer下载安装_mac版flash player
查看>>
java 二维数组元素转换为空格_数组中重复的数字、二维数组中的查找、替换空格--Java知识点解析...
查看>>
java findall_从python到Java的re.findall匹配,模式 - java
查看>>
php加图片源码_php给现有的图片加文字水印代码
查看>>
php 向数据表添加数据_php向表中插入数据
查看>>
php外部,PHP 的外部变量
查看>>
php getticket,easyWechat 处理ticket以及事件推送
查看>>
java获取hive表所有字段,Hive Sql从表中动态获取空列计数
查看>>
java的find怎么使用,新手使用find()有关问题求助
查看>>
JAVA链表取得全部数据,数据结构中的链表,你知道多少?
查看>>
matlab怎么对sinx求导,用matlab程序求y=ln(sinx 1)的导数
查看>>
一阶多智能体matlab,多智能体Q学习算法设计和仿真
查看>>
php中如何导包,import导包和初始化阶段
查看>>
php实现cookie自动登录,PHP使用Cookie实现自动登陆
查看>>
php查百度收录,php检查页面是否被百度收录,可整合到后台
查看>>
matlab lte工具箱,免费试用LTE Toolbox
查看>>
matlab层次分析法运行结果,层次分析法--matlab实现
查看>>
matlab 实验6 高层绘图操作,MATLAB实验报告6高层绘图.doc
查看>>