實在是太頹廢了,所以開始寫點東西吧。。。。
最大子段和: 給定n個數(可能為負整數)組成的序列a1...an,求該序列形如∑ak(i<=k<=j)的子段和的最大值。當所有整數均為負整數時定義其最大的子段和為0.
依據題意我們可以確定 最優值為max(0,max∑ak(i<=i<=j<=n)); 若我們令b[j] = max∑ak(1<=i<=j)是從序列a的第i個數到第j個數的最大和,那麼我們最後的答案就是找出b陣列裡面記錄的最大的那個值就是答案。由b[j]的定義可以知道b[j-1]>0時,b[j] = b[j-1]+a[j]否則b[j] = a[j];由此得出遞推式b[j] = max(b[j-1]+a[j],a[j]) (1<=j<=n)
**如下
1view codeint maxsum1(int n,int *a)29
return
sum;
10 }
最大子段和的推廣
(1)最大子矩陣:給定乙個m行n列的整數矩陣a,求其元素和最大的子矩陣
很明顯最大子矩陣和的問題是最大子段和的問題向二維的推廣,我們用陣列a[1:m][1:n]表示給定的矩陣a 其子陣列a[i1:i2][j1:j2]表示左上角和右下角的行列座標分別為(i1,j1)(i2,j2)的子矩陣 其個各個元素之和 記為 s(i1,i2,j1,j2)= ∑∑a[i][j] (i1<=i<=i2,j1<=j<=j2) 那麼ans = max s(i1,i2,j1,j2) (1<=i1<=i2<=m,1<=j1<=j2<=n)
我們可以令t(i1,i2) = maxs(i1,i2,j1,j2)(i<=j1<=j2<=n) = max∑∑a[i][j] 同樣我們令b[j] = ∑a[i][j](i1<=i<=i2) 於是 t(i1,i2) = max∑b[j](1<=j1<=j2<=n) 這又回到了一維的情況於是我們可以得到如下**
1view codeint maxsum2(int m,int n,int a[105][105
] )212}
13return
sum ;
14 }
最大子矩陣在poj上面有原題目 題號是1050 **如下
#include #includeview code#include
using
namespace
std;
const
int m = 105
;int
a[m][m];
int maxsum1(int n,int *a)
return
sum;
}int maxsum2(int m,int n,int a[105][105
] ) }
return
sum ;
}int
main()
printf(
"%d\n
",maxsum2(n,n,a));
return0;
}
2 最大m子段和
最大子段和是最大m子段和的特殊情況即m = 1時的解,我們用b(i,j)表示陣列a的前j項中i個子段和的最大值 那麼很容易得到如下狀態轉移方程 b(i,j) = max(b(i,j-1),max(b(i-1,t))+a[j] 第乙個狀態表示第i個子段包含a[j],而第二個狀態表示第i個子段只包含a[j] 於是很容易得到如下**
1view codeintmaxsum()211
12}13else
14 b[i][j] = b[i-1][j-1] +a[j];
1516}17
}18int sum = 0;19
for(int j=m;j<=n;j++)
22return
sum ;
23 }
上述演算法顯然需要o(mn^2)但是我們注意到 對b[i][j] 只用到了 第i-1行和第i行因此只要記錄這兩個值就可以,另一方面max(b(i-1,t))的值可以在計算第i-1行是預先計算出來
於是得到優化後的**如下
intview codedp()
c[i+n-m] =tmp;
}printf(
"%d\n
",c[n]);
}
最大m子段和問題在杭電oj上有原題 題號是1024
ac**如下
#include #includeview code#include
using
namespace
std;
const
int m = 1000005
;int
n,m;
inta[m];
intb[m],c[m];
intdp()
c[i+n-m] =tmp;
}printf(
"%d\n
",c[n]);
}int
main ()
return0;
}
最大子段和問題
給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0 分治法 分析 首先將陣列分為兩部分,最大子段和 可以在陣列的左半部分也可以在右半部分,也可以橫跨分割點,因此我們只需要用分治思想求出左邊最大...
最大子段和問題
給定n 個整數 有可能是負數 組成的序列,要求分別用蠻力法,減治法和動態規劃法,求最該序列的最大子段和,並對它們的效率進行比較分析。也稱窮舉法或列舉法,是一種簡單直接地解決問題的方法,常常基於問題的描述,所以,蠻力法也是最容易應用的方法。它依賴的基本技術是遍歷,採用一定的策略依次處理待求解問題的所有...
最大子段和問題
問題描述 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如 a i a i 1 a j 當所給的整數均為負數時定義子段和為0.如果序列中全部是負數則 最大子段和為0,依次所定義 所求的最優值max,1 i問題解析 動態規劃演算法 dp i 包含元素i的子段和 dp 0 ...