POJ 1050 To the Max 矩陣最大和的子數組:動態規劃

將原來的矩陣直接改造成dp矩陣
dp[i][j] 表示以以a[0][0]爲左上角 a[i][j]爲右下角的矩陣之和

所以一個O(n4n^{4})的算法就比較容易寫了

狀態轉移:
表示(不包括)左上角( ii , jj )右下角(i , j)的子矩陣和

ret = max(ret, a[i][j] + a[ii][jj] - a[i][jj] - a[ii][j]);
#include <iostream>
#include <stdio.h>
#include <limits.h>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int a[101][101];
int N;
int ret = INT_MIN;

void disp(){
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
}
int main()
{

    while(cin>>N){
        for(int i=0;i<N*N;i++){
            scanf("%d",&a[i/N][i%N]);
        }
        ret = INT_MIN;
        for(int i=1;i<N;i++){
            a[i][0] = a[i-1][0] + a[i][0];
            a[0][i] = a[0][i-1] + a[0][i];
        }
        for(int i=1;i<N;i++){
            for(int j=1;j<N;j++){
                a[i][j] = a[i][j] + a[i-1][j] + a[i][j-1] - a[i-1][j-1];
                ret = max(ret,a[i][j]);
                //debug(i)
                //debug(j)
                for(int ii=0;ii<i;ii++){
                    ret = max(ret, a[i][j] -a[ii][j]);
                }
                for(int jj=0;j<j;jj++){
                    ret = max(ret, a[i][j] -a[i][jj]);
                }
                for(int ii=0;ii<=i;ii++){
                    for(int jj=0;jj<=j;jj++){
                        //debug(ii)
                        //debug(jj)
                        ret = max(ret, a[i][j] + a[ii][jj] - a[i][jj] - a[ii][j]);
                        //debug(a[i][j] + a[ii][jj] - a[i][jj] - a[ii][j])
                    }
                }
            }
        }
        //disp();
        cout<<ret<<endl;
    }
    return 0;
}

在這裏插入圖片描述

下面是O(n3)O(n^{3})的解法

先求解每一個從i行至j行的第k列的和,從別存入dp[k]
在這裏插入圖片描述
對於dp數組,我們解決最大連續子序列的和即可


#include <iostream>
#include <stdio.h>
#include <limits.h>
#include <string.h>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int a[101][101];
int N;
int ret = INT_MIN;
int dp[101];

void disp(){
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
}

int main(){
    while(cin>>N){
        ret = INT_MIN;
        //memset(a,0,sizeof(a));
        for(int i=0;i<N*N;i++){
            scanf("%d",&a[i/N][i%N]);
        }

        for(int i=0;i<N;i++){
            memset(dp,0,sizeof(dp));
            for(int j=i;j<N;j++){
                for( int k=0;k<N;k++ ){
                    dp[k] += a[ j ][k];
                }
                int temp = 0;
                for( int k=0;k<N;k++ ){
                    temp += dp[k];
                    ret = max(ret,temp);
                    if( temp < 0 ){
                        temp = 0;
                    }

                }
            }
        }
        cout<<ret<<endl;
    }
}

在這裏插入圖片描述

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