【問題描述】
帥帥經常跟同學玩乙個矩陣取數遊戲:對於乙個給定的n*m 的矩陣,矩陣中的每個元素aij均
為非負整數。遊戲規則如下:
1. 每次取數時須從每行各取走乙個元素,共n個。m次後取完矩陣所有元素;
2. 每次取走的各個元素只能是該元素所在行的行首或行尾;
3. 每次取數都有乙個得分值,為每行取數的得分之和,每行取數的得分= 被取走的元素值*2i,
其中i 表示第i 次取數(從1 開始編號);
4. 遊戲結束總得分為m次取數得分之和。
帥帥想請你幫忙寫乙個程式,對於任意矩陣,可以求出取數後的最大得分。
輸入描述 input description
第1行為兩個用空格隔開的整數n和m。
第2~n+1 行為n*m矩陣,其中每行有m個用單個空格隔開的非負整數。
輸出 僅包含1 行,為乙個整數,即輸入矩陣取數後的最大得分。
2 31 2 3
3 4 2
資料範圍及提示 data size & hint
第 1 次:第1 行取行首元素,第2 行取行尾元素,本次得分為1*21+2*21=6
第2 次:兩行均取行首元素,本次得分為2*22+3*22=20
第3 次:得分為3*23+4*23=56。總得分為6+20+56=82
【限制】
60%的資料滿足:1<=n, m<=30, 答案不超過1016
100%的資料滿足:1<=n, m<=80, 0<=aij<=1000
考慮到data[i]*2^n,數字比較大,容易超出longlong容納範圍,因此採用了高精度的寫法。
為了讓**比較簡單,採用分段儲存dp資料,將高16位與低16位分開儲存。
另外就是dp的思路:
將dp[i][j] 定義為,一行中第i個數到第j個數最優取數得分。
狀態轉移方程:dp[i][j] = max( dp[i+1][j]+data[i]*pow(k) , dp[i][j-1]+data[j]*pow(k) );k表示取數的次數。
邊界:dp[i][i] = data[i]*pow(m);m表示列數
#includeusing namespace std;
typedef long long ll;
ll max=1e15;
struct bn;
bn operator+(const bn a,const bn b)
return c;
}int operator<(const bn a,const bn b)
return c;
}void write(const bn a)
bn max(const bn a,const bn b)
for(j=1;jfor(i=1;i<=m-j;i++)
f[i][i+j]=max(f[i+1][i+j]+pow2(m-j)*a[i],f[i][i+j-1]+pow2(m-j)*a[i+j]);
score=score+f[1][m];
} write(score);
}
1166 矩陣取數遊戲 區間dp 高精度
2007年noip全國聯賽提高組 時間限制 1 s 空間限制 128000 kb 題目等級 gold 題解 問題描述 帥帥經常跟同學玩乙個矩陣取數遊戲 對於乙個給定的n m 的矩陣,矩陣中的每個元素aij均 為非負整數。遊戲規則如下 1.每次取數時須從每行各取走乙個元素,共n個。m次後取完矩陣所有元...
P1005 矩陣取數遊戲 區間dp 高精度
帥帥經常跟同學玩乙個矩陣取數遊戲 對於乙個給定的n times mn m的矩陣,矩陣中的每個元素a ai,j 均為非負整數。遊戲規則如下 每次取數時須從每行各取走乙個元素,共nn個。經過mm次後取完矩陣內所有元素 每次取走的各個元素只能是該元素所在行的行首或行尾 每次取數都有乙個得分值,為每行取數的...
區間DP 矩陣取數遊戲
試題 noip2007 提高組 問題描述 帥帥經常跟同學玩乙個矩陣取數遊戲 對於乙個給定的 n m的矩陣,矩陣中的每個元素 aij均為非負整數。遊戲規則如下 1.每次取數時須從每行各取走乙個元素,共 n個。m次後取完矩陣所有元素 2.每次取走的各個元素只能是該元素所在行的行首或行尾 3.每次取數都有...