zoukankan      html  css  js  c++  java
  • 最大子矩阵

    #include<iostream>
    using namespace std;
    #define MAX 100010
    //用你自己的思维解决问题
    
    long long v[MAX],height[MAX],dp[MAX],maxn;
    int main(){
        int n;
        while(cin>>n){
            if(n==0) break;
            memset(height,0,sizeof(height));
            memset(dp,0,sizeof(dp));
            memset(v,0,sizeof(v));
            for(int i=0;i<n;i++)
                cin>>height[i];
            dp[0]=height[0];
            v[0]=height[0];
        for(int i=1;i<n;i++){
        if(v[i-1]>height[i]){//连成一片截别人
            v[i]=height[i];
            dp[i]=(dp[i-1]/v[i-1]+1)*height[i];
         }
         else {  //连成一片截自己
           if(dp[i-1]+v[i-1]>=height[i]){
            v[i]=v[i-1];
            dp[i]=dp[i-1]+v[i];
           }
             else{  // 自己独成一片
            v[i]=height[i];
            dp[i]=height[i];
             }
            }
        }
         maxn=0;
        for(int i=0;i<n;i++){
            if(dp[i]>maxn)
                maxn=dp[i];
        }
      cout<<maxn<<endl;
        
        }
        return 0;
    }

     觉得自己挺对的,一般测试数据都能过,但是没有A,到底是哪里出了问题,理一下思路吧

    要找出最大子矩阵,那么对于当前这块木板,

    1)如果它比左边的矩阵的高度短,那么肯定是截取左边的矩阵,使其高度和自己一样高

    2)如果它比左边矩阵的高度大的话,那么可以考虑截取自己的高度,和左边矩阵的高度一样,还是自己独立成为一个新的矩阵

    有一种思路是对于每个单位矩阵,求每个矩形向2边延伸的最大长度,用2个数组来记录,l[i],表示第i个矩形左边的最大下标,

    r[i] ,表示第i个矩阵右边的最大下标。 

    这样每个人矩阵的面积就可以为

    S[i]=(r[i]-l[i]+1)*height[i];

    最后求出最大的s[i];

    感觉这种思维比起我的,更宏观一点,突然发现我的思维是有问题的,在第一点那个地方,如果所谓的左边的那个矩阵的左边的高度比当前这个还大呢,那样我们就可以一同截取了,所以我的思维是错误的。不好意思~~,算法就是让我们的思维更加缜密~~

    那么如何找到l[i]呢,一个一个地比较吗?这时动规排上了用场

    右扫一遍,求出每个点的l保存在l[]数组里,然后从右到左扫一遍,求出每个点的r保存在r[]数组里,最后可以求出最大的矩阵了。

    利用动态规划,如果它左边高度大于等于它本身,那么它左边的左边界一定满足这个性质,再从这个边界的左边迭代下去

    正确代码:

    #include<iostream>
    using namespace std;
    #define MAX 100010
    //用你自己的思维解决问题
    
    long long height[MAX],l[MAX],r[MAX],maxn,S[MAX];
    int main(){
        int n;
    	long long t;
        while(cin>>n){
            if(n==0) break;
            memset(height,0,sizeof(height));
            memset(l,0,sizeof(l));
            memset(r,0,sizeof(r));
    		memset(S,0,sizeof(S));
            for(int i=1;i<=n;i++)
                cin>>height[i];
    	  l[1]=1;r[n]=n;
    		 for(int i=2;i<=n;i++)//求每个点左边连续比它大的最左边的下标,保存在l[]数组里
          {
              t=i;
    		  while(t>1&&height[i]<=height[t-1]) 
                  t=l[t-1];
              l[i]=t;
          }
          for(int i=n-1;i>=1;i--)//求每个点右边连续比它大的最右边的下标,保存在r[]数组里
          {
              t=i;
              while(t<n&&height[i]<=height[t+1])
                  t=r[t+1];
              r[i]=t;
          }
    		maxn=0;
    		for(int i=1;i<=n;i++){
    			S[i]=(r[i]-l[i]+1)*height[i];
    			if(S[i]>maxn)
    				maxn=S[i];
    		}
    
    		cout<<maxn<<endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    结对项目开始
    团队项目开始
    个人项目总结
    python面向对象
    OSI七层模型
    Django中的orm的惰性机制
    Python装饰器
    python运算符
    python元祖和列表
    Sencha Touch 1.x 快速入门 第三章 布局(2) Card布局
  • 原文地址:https://www.cnblogs.com/wintersong/p/4982945.html
Copyright © 2011-2022 走看看