日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Tyvj Aug11] 黄金矿工

發布時間:2023/12/29 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Tyvj Aug11] 黄金矿工 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

Description

黃金礦工是一個經典的小游戲,它可以鍛煉人的反應能力。該游戲中,可以通過“挖礦”獲得積分并不斷升級。玩家可以在線玩flash版黃金礦工,也可以下載后玩單機版黃金礦工。目前,黃金礦工小游戲有多個版本,例如黃金礦工雙人版,黃金礦工單人版等。

Jimmy是一位黃金礦工,他所在的金礦是一個n*n的矩形區域(俯視),區域內有黃金、石頭和TNT,由一個 n*n的矩陣描述。黃金的價值對應矩陣中的正值,石頭的價值對應矩陣中的負值,TNT由0表示。換句話說,挖到黃金賺錢,石頭虧損,如果挖到TNT就掛了。

Jimmy租到的挖礦工具很特別,它的形狀是一個長寬任意(均為正整數)的矩形,可以取走被該工具覆蓋的矩形區域內的所有物品,但如果該區域內有TNT,該工具將被炸毀,此時Jimmy將不得不賠償礦主+∞元!!!需要注意的是,該工具只能在金礦范圍內使用(即不得超出金礦邊界),且租金為每次使用十元。

現在,Jimmy想知道,如果他至多只有一次租用該工具的機會,他能獲得的最大收益是多少。當然,如果Jimmy租用該工具無論如何都會虧損,他可以不租用,此時收益為0.

Input

第一行:一個整數n
接下來n行,每行n個整數(絕對值<100),為題目中所描述的矩陣。

Output

一個數,即Jimmy所能獲得的最大收益。

Sample Input

3
0 -1 -1
0 -12 0
-19 0 0

Sample Output

0

Hint

【樣例解釋】
無論Jimmy怎么挖礦,挖到的不是石頭,就是TNT,總之無論如何都會虧損,所以選擇不租用工具,收益為0

【數據范圍】
對于30%的數據:0<n<=10
對于60%的數據:0<n<=100
對于100%的數據:0<n<=300

Source

動態規劃, 貪心,子矩陣DP

?

?

這是一道很好的DP題,首先這道題的模型就是求最大子矩陣和。很容易想到的暴力枚舉是O(n^4)的,顯然會TLE,我們發現,暴力枚舉的時候我們很多東西都重復計算了,沒有很好的利用中間結果。

首先從一維的子序列最大和講起。對于任意數列,O(n)的求它最大的子序列和,設f[i]表示到i位置的最大和,那么狀態的轉移只有兩種,如果f[i-1]>0,那么 f[i]=f[i-1]+a[i],否則f[i]=a[i]。因為要求最大的子序列和,所以所選的子序列的起始位置一定是正數。

當f[i]>0時,這個轉移顯然是對的,(每次轉移后都會更新答案,所以a[i]<0也不會影響答案)

當f[i-1]<0時,f[i-1]+a[i]一定小于 a[i],而i-1是從上一個起始位置開始,一段子序列中和第一次小于0的位置,同時序列的起點又是正數,所以上一次選的序列中不存在一個位置到當前位置的序列和大于0,所以新序列從 i 位置開始。

然后類比到二維的子矩陣和,我們可以把一個矩形一列的和看做一維數組的一個元素,轉化為上面那個問題,這樣就只需枚舉矩形的上下界,求和的話可以用前綴和優化,記錄每一列的前綴和,這樣就可以O(1)求矩形一列的和。總復雜度為O(n^3)。

還可以參見這篇博客,博主講得很清楚。

?

?

1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define ll long long 16 17 inline int gi() 18 { 19 bool b=0; int r=0; char c=getchar(); 20 while(c<'0' || c>'9') { if(c=='-') b=!b; c=getchar(); } 21 while(c>='0' && c<='9') { r=r*10+c-'0'; c=getchar(); } 22 if(b) return -r; return r; 23 } 24 25 const int inf = 21400000, N = 307; 26 int a[N][N]; 27 28 int main() 29 { 30 int i,j,k,sum,ans,n; 31 n=gi(); 32 for (i=1; i<=n; i++) 33 for (j=1; j<=n; j++) 34 { 35 a[i][j]=gi(); 36 if (!a[i][j]) a[i][j]=-inf; 37 a[i][j]+=a[i-1][j]; //記錄每一列的前綴和 38 } 39 for (i=1; i<=n; i++) //枚舉子矩形下面邊的位置 40 for (k=0; k<i; k++) //枚舉子矩形上面邊的位置 41 { 42 sum=0; 43 for (j=1; j<=n; j++) //枚舉矩形的寬 若 sum 大于 0 則繼續擴展 每次更新 ans 否則 sum=0 重新枚舉一個子矩形 妙不可言 44 { 45 sum+=a[i][j]-a[k][j]; 46 if (sum < 0) sum=0; 47 else ans=max(ans,sum); 48 } 49 } 50 printf("%d\n",max(ans-10,0)); 51 return 0; 52 }

?

轉載于:https://www.cnblogs.com/y142857/p/7152992.html

總結

以上是生活随笔為你收集整理的[Tyvj Aug11] 黄金矿工的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。