今天想到了昨天看到一道acm題目,難度入門級別。“誰看的最多”,題目大概是這樣的:一隊列的人3 2 1 6 4 5,數值的大小表示該人的高度。每個人只能看到前面比他高的人,如1可以看見2、3。但是,如果有人B比他高,那么他就不能看到這那個B之前比B低的人了。如5,因為6比他高,他只能看到6,但看不到6之前的人(如果之前有7、8之類比6高的,5也可以看到)。而4比5低也看不到。
題目想了個大概就沒有想了,又是卡在里動態規劃的狀態里。F(i)表示第i個人看到的人數。如果他前一個人比i低,則i看到的最多只有一個了,就是i-1。如果他比前一個高,則看到的就是前i-1個人第一個比他高的人看的人數加一。如果可以快速找前面i-1的第一個比i高,就可以利用動態規劃的方法了。通過一個數組記錄i前面的第一個比i高的位置,這樣就可以快速找出。
狀態轉移方程:F(i)=若i比i-1高,為F(j)+1,j為前面的第一比i高的;否則為1(i>0。i=0,看到就為0個)
挫挫代碼:
1 int func10(int a[], int n) 2 { 3 int i,j; 4 int maxsee; 5 int *see,*tall; 6 7 if (n<0) 8 { 9 return -1; 10 } 11 see = (int*)malloc(n*sizeof(int)); 12 tall = (int*)malloc(n*sizeof(int)); 13 14 maxsee = see[0] = 0; 15 tall[0] = -1; //之前未有比其高的 16 17 for (i=1; i<n; i++) 18 { 19 if (a[i] > a[i-1]) 20 { 21 for (j=tall[i-1]; j>0; ) 22 { 23 if (a[i]<=a[j]) 24 { 25 break; 26 } 27 j=tall[j]; 28 } 29 if (j==-1) 30 { 31 see[i] = 0; 32 tall[i] = -1; 33 } 34 else 35 { 36 see[i] = see[j] +1; 37 tall[i] = j; 38 } 39 } 40 else //a[i]<=a[i-1] 41 { 42 see[i] = see[i-1]+1; 43 tall[i] = i-1; 44 } 45 46 maxsee = maxsee<see[i] ? see[i] : maxsee; 47 } 48 49 free(see); 50 free(tall); 51 52 return maxsee; 53 54 }
又一題。
復習還是不給力。。。繼續。。
畢。
?修訂2013-4-18 :
在不斷的被虐之后,發現其是這個算法的題目是ACM中一個犀利的數據結構:單調棧的應用(參考博客中的另一篇文章:單調棧:柱形統計圖中最大面積(POJ 2559))?其實此問題的解決就是單調棧的思想,通過記錄的一些信息模擬單調棧。其算法復雜度和單調棧是一致的。