zoukankan      html  css  js  c++  java
  • 悬线法练习

    在此感谢那个网名叫顾z的人。

    悬线法:

    目标:求给定矩阵中满足条件的最大子矩阵

    方法:left[i][j]表示(i,j)所能到达的最左位置 , right[i][j]类似 , up[i][j]表示往上扩展的最大长度。

    递推公式: left[i][j]=max(left[i][j],left[i−1][j]) right[i][j]=min(right[i][j],right[i-1][j])

    正确性显然, 适用性可能不是那么通用。

    讲解更好的博客:https://www.luogu.com.cn/blog/RPdreamer/p1169

    
    //悬线法求解最大规模子矩阵板子
    
    int main()
    {
    	
    	cin >> n >> m;
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    		{
    			cin >> a[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<=n; ++j)
    			if(……)
    				left[i][j] = left[i][j-1];
    	
    	for(int i=1; i<=n; ++i)
    		for(int j=n-1; j>=1; --j)
    			if(……)
    				right[i][j] = right[i][j+1];
    	
    	//处理up=1时的right与left数组
    	
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    		{
    			
    			if(i>1 && ……)
    			{
    				
    				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;
    			}
    			
    			/* calc ans */
    			
    			
    			
    		}
    		
    	cout << ans;
    		
    	
    	return 0;
    	
     } 
    
    
    

    例题:https://www.luogu.com.cn/problem/P1387

    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 105;
    
    int n, m, a[maxn][maxn];
    int up[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
    
    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]);
    			l[i][j] = r[i][j] = j;
    			up[i][j] = 1;
    		}
    		
    	for(int i=1; i<=n; ++i)
    		for(int j=2; j<=m; ++j)
    			if(a[i][j-1] && a[i][j])
    				l[i][j] = l[i][j-1];
    	
    	for(int i=1; i<=n; ++i)
    		for(int j=m-1; j>=1; --j)
    			if(a[i][j+1] && a[i][j])
    				r[i][j] = r[i][j+1];
    	
    	int ans = 0;
    	
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    		if(a[i][j] == 1)
    		{
    			
    			if(i>1 && a[i-1][j] && a[i][j])
    			{
    				l[i][j] = max(l[i][j], l[i-1][j]);
    				r[i][j] = min(r[i][j], r[i-1][j]);
    				up[i][j] = up[i-1][j] + 1;
    			}
    			
    			int a = r[i][j] - l[i][j] + 1;
    			int b = up[i][j];
    			ans = max(ans, min(a,b));
    			
    		}
    	
    	cout << ans;
    	
    	return 0;
    	
    }
    
    

    例题:https://www.luogu.com.cn/problem/P1169

    
    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int maxn = 2005;
    
    int n, m, a[maxn][maxn];
    
    int l[maxn][maxn], r[maxn][maxn], up[maxn][maxn];
    
    int main()
    {
    	
    	cin >> n >> m;
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    		{
    			scanf("%d", &a[i][j]);
    			l[i][j] = r[i][j] = j;
    			up[i][j] = 1;
    		}
    		
    	for(int i=1; i<=n; ++i)
    		for(int j=2; j<=m; ++j)
    			if(a[i][j] != a[i][j-1])
    				l[i][j] = l[i][j-1];
    	
    	for(int i=1; i<=n; ++i)
    		for(int j=m-1; j>=1; --j)
    			if(a[i][j] != a[i][j+1])
    				r[i][j] = r[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 && a[i][j] != a[i-1][j])
    			{
    				l[i][j] = max(l[i][j], l[i-1][j]);
    				r[i][j] = min(r[i][j], r[i-1][j]);
    				up[i][j] = up[i-1][j] + 1;
    			}
    			
    			int a = r[i][j] - l[i][j] + 1;
    			int b = up[i][j];
    			
    			ans1 = max(ans1, min(a,b)*min(a,b) );
    			ans2 = max(ans2, a*b);
    			
    		}
    	
    	cout << ans1 << '
    ' << ans2;
    	
    	return 0;
    	
    }
    
  • 相关阅读:
    Keras安装
    sql根据查询顺序返回结果
    @Configuration @Bean
    SQL高级优化系列
    数据结构与算法系列(二)-- 算法
    数据结构与算法系列(一)-- 数据结构
    Golang中Label的用法
    日志收集系统系列(五)之LogTransfer
    日志收集系统系列(四)之LogAgent优化
    日志收集系统系列(三)之LogAgent
  • 原文地址:https://www.cnblogs.com/tztqwq/p/12312082.html
Copyright © 2011-2022 走看看