洛谷 P1005 矩陣取數遊戲 區間dp

2021-09-25 23:21:35 字數 1808 閱讀 5183

帥帥經常跟同學玩乙個矩陣取數遊戲:對於乙個給定的n \times mn×m的矩陣,矩陣中的每個元素a_ai,j​均為非負整數。遊戲規則如下:

每次取數時須從每行各取走乙個元素,共nn個。經過mm次後取完矩陣內所有元素;

每次取走的各個元素只能是該元素所在行的行首或行尾;

每次取數都有乙個得分值,為每行取數的得分之和,每行取數的得分 = 被取走的元素值\times 2^i×2i,其中ii表示第ii次取數(從11開始編號);

遊戲結束總得分為mm次取數得分之和。

帥帥想請你幫忙寫乙個程式,對於任意矩陣,可以求出取數後的最大得分。

輸入檔案包括n+1n+1行:

第11行為兩個用空格隔開的整數nn和mm。

第2\backsim n+12∽n+1行為n \times mn×m矩陣,其中每行有mm個用單個空格隔開的非負整數。

輸出檔案僅包含11行,為乙個整數,即輸入矩陣取數後的最大得分。

輸入 #1複製

2 3

1 2 3

3 4 2

輸出 #1複製

82
noip 2007 提高第三題

資料範圍:

60%的資料滿足:1\le n, m \le 301≤n,m≤30,答案不超過10^1016

100%的資料滿足:1\le n, m \le 801≤n,m≤80,0 \le a_ \le 10000≤ai,j​≤1000

有乙個n*m大小的矩陣,求n行最大得分和,每一行取數又不會影響到其他行,那麼只要確保每一行得分最大就好。

每次取數都在邊緣取,那麼取數後剩下的元素也一定在某個完整的區間內。於是可以考慮對矩陣每一行進行區間dp

令dp[i][j]為在矩陣第l行時,區間[i,j]中能獲得的最大分數。

這個我們已經比較熟悉了,顯然dp[i][j]可以從區間[i-1,j]轉移過來,也可以從[i,j+1]轉移過來,取個max。可以在第m-j+i-1次取走a[i-1][j]或者a[i][j+1]。

dp[i][j]=max(dp[i-1][j]+a[i-1][j]×2^,dp[i][j+1]+a[i][j+1]×2^)

最後列舉一下長度為1的區間。答案為

s=max(s,dp[i][i]+a[i][i]×2^)

由於本題資料比較毒瘤,即使推對了dp也只能得60。本蒟蒻不會寫高精度於是只好偷懶用了__int128。(逃)

注意,__int128不能用cin或cout讀,可以自己寫乙個或者用快讀快寫讀寫也行。

我在本題中實現$2$的冪次方是用字首做的,對於每個$p[i]$代表$2^$。

#include #include #include #include #define r(x) x=read()

#define bll __int128

using namespace std;

bll n,m,k,s,dp[101][101],a[101][101],p[101];

inline int read()

while(ch>='0' && ch<='9')

return x*w;

}void write(bll x)

signed main()

} for(l=1;l<=n;l++)

}bll maxn(0);

for(i=1;i<=m;i++)

s+=maxn;//加上這一行的分數

} if(s==0) cout<<0

cout

}

洛谷 P1005 矩陣取數遊戲(區間DP)

會發現每一行之間沒有影響,可以做n次區間dp。設dp i j 表示區間 i,j 的取分最大值。如果從小區間向大區間轉移,即 dp i j max dp i 1 j a i dp i j 1 a j 2 這樣 2 i 在轉移的過程中便之間乘上了。ac 無高精 1 include2 include3 i...

洛谷p1005矩陣取數遊戲

原題 2 80超int,需要高精度計算,也可以int128.行和行之間沒有聯絡,所以只要單獨求每一行之後取和即可,dp過程中i,j分別表示左端點和右端點。include define lll int128 void print lll x int n,m lll ans 0 int a 100 ll...

洛谷 P1005 矩陣取數遊戲

好多題解的f i j 表示還剩 i j 沒取的最大值,如果這樣寫的話,最後還要取個max f i i a i 2 m 如果轉化一下題意來做也是可以的。include define int int128 不會高精,只能 int128水一波了,如果考試考到,也只能放棄了 using namespace ...