最大連續子序列和最大連續子矩陣的關係與實現

【算法小總結】最大連續子序列和最大連續子矩陣的關係與實現

    <div class="article_manage clearfix">
    <div class="article_l">
        <span class="link_categories">
        標籤:
          <a href="http://www.csdn.net/tag/%e6%9c%80%e5%a4%a7%e8%bf%9e%e7%bb%ad%e5%ad%90%e5%ba%8f%e5%88%97%e5%92%8c%e6%9c%80%e5%a4%a7%e8%bf%9e%e7%bb%ad%e5%ad%90%e7%9f%a9%e9%98%b5%e7%9a%84%e5%85%b3%e7%b3%bb%e4%b8%8e%e5%ae%9e" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">最大連續子序列和最大連續子矩陣的關係與實</a><a href="http://www.csdn.net/tag/C%e8%af%ad%e8%a8%80%20ACM%20C%2b%2b%20OJ" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">C語言 ACM C++ OJ</a>
        </span>
    </div>
    <div class="article_r">
        <span class="link_postdate">2014-08-15 10:04</span>
        <span class="link_view" title="閱讀次數">1118人閱讀</span>
        <span class="link_comments" title="評論次數"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">評論</a>(0)</span>
        <span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('%e3%80%90%e7%ae%97%e6%b3%95%e5%b0%8f%e6%80%bb%e7%bb%93%e3%80%91%e6%9c%80%e5%a4%a7%e8%bf%9e%e7%bb%ad%e5%ad%90%e5%ba%8f%e5%88%97%e5%92%8c%e6%9c%80%e5%a4%a7%e8%bf%9e%e7%bb%ad%e5%ad%90%e7%9f%a9%e9%98%b5%e7%9a%84%e5%85%b3%e7%b3%bb%e4%b8%8e%e5%ae%9e%e7%8e%b0','38580931');return false;" title="收藏" target="_blank">收藏</a></span>
         <span class="link_report"> <a href="#report" onclick="javascript:report(38580931,2);return false;" title="舉報">舉報</a></span>

    </div>
</div>    <style type="text/css">        
        .embody{
            padding:10px 10px 10px;
            margin:0 -20px;
            border-bottom:solid 1px #ededed;                
        }
        .embody_b{
            margin:0 ;
            padding:10px 0;
        }
        .embody .embody_t,.embody .embody_c{
            display: inline-block;
            margin-right:10px;
        }
        .embody_t{
            font-size: 12px;
            color:#999;
        }
        .embody_c{
            font-size: 12px;
        }
        .embody_c img,.embody_c em{
            display: inline-block;
            vertical-align: middle;               
        }
         .embody_c img{               
            width:30px;
            height:30px;
        }
        .embody_c em{
            margin: 0 20px 0 10px;
            color:#333;
            font-style: normal;
        }
</style>
<script type="text/javascript">
    $(function () {
        try
        {
            var lib = eval("("+$("#lib").attr("value")+")");
            var html = "";
            if (lib.err == 0) {
                $.each(lib.data, function (i) {
                    var obj = lib.data[i];
                    //html += '<img src="' + obj.logo + '"/>' + obj.name + "&nbsp;&nbsp;";
                    html += ' <a href="' + obj.url + '" target="_blank">';
                    html += ' <img src="' + obj.logo + '">';
                    html += ' <em><b>' + obj.name + '</b></em>';
                    html += ' </a>';
                });
                if (html != "") {
                    setTimeout(function () {
                        $("#lib").html(html);                      
                        $("#embody").show();
                    }, 100);
                }
            }      
        } catch (err)
        { }

    });
</script>
  <div class="category clearfix">
    <div class="category_l">
       <img src="http://static.blog.csdn.net/images/category_icon.jpg">
        <span>分類:</span>
    </div>
    <div class="category_r">
                <label onclick="GetCategoryArticles('2440523','u013517797','top','38580931');">
                    <span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">算法小總結<em>(7)</em></span>
                  <img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;">
                  <img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;">
                    <div class="subItem">
                        <div class="subItem_t"><a href="http://blog.csdn.net/u013517797/article/category/2440523" target="_blank">作者同類文章</a><i class="J_close">X</i></div>
                        <ul class="subItem_l" id="top_2440523">                            
                        </ul>
                    </div>
                </label>                    
    </div>
</div>
    <div class="bog_copyright">         
        <p class="copyright_p">版權聲明:本文爲博主原創文章,未經博主允許不得轉載。</p>
    </div>

最大連續子序列和最大連續子矩陣的關係與實現

 

求最長連續子序列的優化方法(非DP)
//求最大連續子序列和與對應的開頭元素和結束元素
實現代碼:

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<algorithm>  
  4. #include<limits.h>  
  5. #define MAXN 100002   
  6. using namespace std;  
  7. int main()  
  8. {  
  9.     int i,j,n,a[MAXN],Max,sum,max;  
  10.     int ps,pe,ts,te;//記錄開頭元素和結束元素   
  11.       
  12.     scanf(”%d”,&n);  
  13.     for(i=0;i<n;i++)  
  14.     scanf(”%d”,&a[i]);  
  15.       
  16.     sum=0;  
  17.     Max=INT_MIN;  
  18.       
  19.     for(i=0;i<n;i++)  
  20.     {  
  21.         if(sum<=0)//如果序列和爲負數,初始化sum與開始結束下標   
  22.         {  
  23.            sum=a[i];  
  24.            ts=i;  
  25.            te=i;  
  26.         }  
  27.         else//如果序列和爲正數,繼續累加,並記錄新的結尾座標   
  28.         {  
  29.            sum+=a[i];  
  30.            te=i;  
  31.         }  
  32.           
  33.         if(sum>Max)//一旦發現更大的連續子序列,就更新最大值和開始結束下標   
  34.         {  
  35.           Max=sum;  
  36.           ps=ts;  
  37.           pe=te;  
  38.         }  
  39.     }  
  40.       
  41.     printf(”%d %d %d\n”,Max,a[ps],a[pe]);   
  42.     return 0;  
  43. }  
#include<stdio.h>




#include<string.h> #include<algorithm> #include<limits.h> #define MAXN 100002 using namespace std; int main() { int i,j,n,a[MAXN],Max,sum,max; int ps,pe,ts,te;//記錄開頭元素和結束元素 scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); sum=0; Max=INT_MIN; for(i=0;i<n;i++) { if(sum<=0)//如果序列和爲負數,初始化sum與開始結束下標 { sum=a[i]; ts=i; te=i; } else//如果序列和爲正數,繼續累加,並記錄新的結尾座標 { sum+=a[i]; te=i; } if(sum>Max)//一旦發現更大的連續子序列,就更新最大值和開始結束下標 { Max=sum; ps=ts; pe=te; } } printf("%d %d %d\n",Max,a[ps],a[pe]); return 0; }


 

例子:
8
1 -3 -5 2 6 -1 4 9
20 2 9

 

類似的是,在矩陣中求最大子矩陣的方法可以轉化成一維求最大連續子序列和的方法。

將矩陣的行或列壓縮。這裏我選擇列壓縮
如:    
1 -1 2
4 9 15
-7 1 10


計算每一遞進行的最長連續子序列和,什麼是遞進行?舉個例子
全局變量MAX=-999999999

剛剛的矩陣
1 -1 2
4 9 15
-7 1 10
————————————————————————————————————
第一次記算取 1 -1 2
求出最長連續子序列是2,MAX=2

第二次取
1 -1 2
4 9 15
這裏兩行的每一列元素之和:5 8 17(從這裏開始就體現矩陣壓縮了)
求出最長連續子序列是30,MAX=30

第三次取
1 -1 2
4 9 15
-7 1 10
這裏三行的每一列元素之和:-2 9 27
求出最長連續子序列是36,MAX=36
————————————————————————————————————
第四次取:4 9 15
求出最長連續子序列是28,MAX=36

第五次取
4 9 15
-7 1 10
這裏兩行的每一列元素之和:-3 10 25
求出最長連續子序列是35,MAX=36
————————————————————————————————————
第六次次取:-7 1 10
求出最長連續子序列是11,MAX=36
————————————————————————————————————
到此爲止,所有可能的子矩陣和全都計算完畢,得出最大的子矩陣元素之和爲36
即是
-1 2
9 15
1 10
這個子矩陣

 

實現代碼:

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <limits.h>  
  4. #define MAXN 10002  
  5. int a[MAXN][MAXN],temp[MAXN];  
  6. int n;  
  7. int getsum()  
  8. {  
  9.    int i,sum=0,max=0;  
  10.    for(i=0;i<n;i++)  
  11.    {  
  12.       sum+=temp[i];  
  13.       if(sum>max) max=sum;  
  14.       if(sum<0) sum=0;   
  15.    }  
  16.    return max;  
  17. }  
  18. int main()  
  19. {  
  20.     int i,j,ans,k;   
  21.  while(scanf(“%d”,&n)!=EOF)  
  22.     {  
  23.        memset(a,0,sizeof(a));  
  24.     for(i=0;i<n;i++)  
  25.          for(j=0;j<n;j++)  
  26.          scanf(”%d”,&a[i][j]);  
  27.       ans=INT_MIN;  
  28.       for(i=0;i<n;i++)//從第i行開始   
  29.       {  
  30.          memset(temp,0,sizeof(temp));  
  31.          for(j=i;j<n;j++)//從 i行到 n-1行都嘗試一次   
  32.          {  
  33.             for(k=0;k<n;k++)//把 j至 k行的每一列都加起來,就是矩陣壓縮   
  34.              temp[k]+=a[j][k];   
  35.                
  36.              int pre=getsum();//計算壓縮矩陣形成的一維數組的最長連續序列   
  37.              if(ans<pre)//更新最大值   
  38.                 ans=pre;   
  39.          }  
  40.       }   
  41.       printf(”%d\n”,ans);  
  42.  }  
  43.  return 0;  
  44. }  
#include <stdio.h>




#include <string.h> #include <limits.h> #define MAXN 10002 int a[MAXN][MAXN],temp[MAXN]; int n; int getsum() { int i,sum=0,max=0; for(i=0;i<n;i++) { sum+=temp[i]; if(sum>max) max=sum; if(sum<0) sum=0; } return max; } int main() { int i,j,ans,k; while(scanf(“%d”,&n)!=EOF) { memset(a,0,sizeof(a)); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf(“%d”,&a[i][j]); ans=INT_MIN; for(i=0;i<n;i++)//從第i行開始 { memset(temp,0,sizeof(temp)); for(j=i;j<n;j++)//從 i行到 n-1行都嘗試一次 { for(k=0;k<n;k++)//把 j至 k行的每一列都加起來,就是矩陣壓縮 temp[k]+=a[j][k]; int pre=getsum();//計算壓縮矩陣形成的一維數組的最長連續序列 if(ans<pre)//更新最大值 ans=pre; } } printf(“%d\n”,ans); } return 0; }

 

剛剛的例子答案:
3
1 -1 2
4 9 15
-7 1 10
36
驗證方法無誤~


歡迎訪問程序員之洞http://blog.csdn.net/acmman/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章