hello_cosmos的專欄
阿新 • • 發佈:2019-01-05
還是動態規劃
題目大意:
給定一個N*N的矩陣,在矩陣中尋找一個h*w的矩陣,使得對於所有可能的矩陣,這個矩陣的所有元素和最大,並輸出這個最大值。
-------------------------------------------------割啊割啊割啊割啊割啊割------------------------------------------------------
額,一開始呢,我覺得這是一道蠻有挑戰性的題目...結果...
其實一開始我還是分析了這題目的子結構什麼的,結果發現,這道題可以直接轉換成一維的最大子序列和問題。轉換的關鍵就是,對於同一列,按照不同的方式求和(當然上下保證要連續的),然後將同一種求和方式排成一行,對這一行求取最大子序列和,遍歷完所有的求和方式,就OK了...
當然你也可以對於每一行來做這個,不過由於計算機儲存方式的關係,用行的話會增加快取的換入換出,減少快取的命中率。速度會變慢的。
好了,其實這道題沒有什麼新鮮的東西,唯一說一下的就是在記憶體的限制下,需要節約空間來做這個。
直接上程式碼吧。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_L 100 //(2*100^2)*4+100= 80000 = 80k int a[MAX_L][MAX_L]; int sum[MAX_L][MAX_L]; int totalMax=-12800; //儲存最終結果的,求和最小值不會超過-127*100 int findMax(int N){ int rowP[MAX_L]; //臨時陣列 int max,i,j; int *sumRowP,*rowA; int row; for (row=0;row<N;row++){ for (i=0;i<(N-row);i++){ sumRowP=sum[i]; rowA=a[row+i]; for (j=0;j<N;j++){ //s(i,j)代表在輸入矩陣中,以第i行第j個元素為起始,垂直長度為row+1的列的和。 sumRowP[j]+=rowA[j]; } rowP[0]=sumRowP[0]; //問題轉化成,在這個行中,求最大子序列的問題 for (j=1;j<N;j++){ //一維最大子序列和的問題 if (rowP[j-1]<0){ rowP[j]=sumRowP[j]; }else{ rowP[j]=rowP[j-1]+sumRowP[j]; } } max=-12800; for (j=0;j<N;j++){ if (rowP[j]>max) max=rowP[j]; //求出的max就是在垂直長度為row+1的所有矩形中,矩形內元素和的最大值 } if (totalMax<max) totalMax=max; //儲存最終結果的 } } } int main(){ int N,i,j; scanf("%d",&N); for (i=0;i<N;i++){ for (j=0;j<N;j++){ scanf("%d",&a[i][j]); } } memset(sum,0,MAX_L*MAX_L*sizeof(int)); findMax(N); printf("%d",totalMax); return 0; }
就這樣~加油!