題目描述 description
帥帥經常跟同學玩乙個矩陣取數遊戲:對於乙個給定的n*m的矩陣,矩陣中的每個元素aij均為非負整數。遊戲規則如下:
1.每次取數時須從每行各取走乙個元素,共n個。m次後取完矩陣所有元素;
2.每次取走的各個元素只能是該元素所在行的行首或行尾;
3.每次取數都有乙個得分值,為每行取數的得分之和,每行取數的得分 = 被取走的元素值*2^i,其中i表示第i次取數(從1開始編號);
4.遊戲結束總得分為m次取數得分之和。
帥帥想請你幫忙寫乙個程式,對於任意矩陣,可以求出取數後的最大得分
輸入格式:
輸入檔案game.in包括n+1行:
第1行為兩個用空格隔開的整數n和m。
第2~n+1行為n*m矩陣,其中每行有m個用單個空格隔開的非負整數。
資料範圍:
60%的資料滿足:1<=n, m<=30,答案不超過10^16
100%的資料滿足:1<=n, m<=80,0<=aij<=1000
輸出格式:
輸出檔案game.out僅包含1行,為乙個整數,即輸入矩陣取數後的最大得分。
樣例測試點#1
noip 2007 提高第三題
2 31 2 3
3 4 2
82
#include #include #include #include #include #include #include #include using namespace std;
const int maxn=82;
int ans[maxn],p[maxn],n,m,f[maxn][maxn][32],er[maxn][maxn];
int fpi[maxn],spi[maxn];
int fsum[maxn],ssum[maxn];
inline int get()
inline void mul(int *a,int *b,int x)
while(c[c[0]+1])++c[0],c[c[0]]+=c[c[0]-1]/10,c[c[0]-1]%=10;
for(int i=0;i<=30;++i)a[i]=c[i];
}inline void add(int *q,int *a,int *b)
if(c[c[0]+1])++c[0];
for(int i=0;i<=30;++i)q[i]=c[i];//不知道為什麼要到30(或》)而不是c[ 0 ],掛了乙個點
}inline bool mx(int *a,int *b)
思路:剛開始想的貪心是錯的,本來認為每次取頭尾二者中的最小值,可結果不一定最優。已知最終結果等於每行最大結果的和,想到dp,即f[ i ][ j ]表示從i到j的數最大解=max(f[ i ][ j-1] +a[j]*2^x,f[ i+1 ][ j ]+a[ i ]*2^x);f[ 1 ][ m ]即為該行最大解。再用高精。 洛谷1005 矩陣取數遊戲
傳送門 思路 首先當然是每行單獨處理 再把答案相加 我們發現如果知道還沒有取數的區間長度 就知道現在取了多少個數 也就是說我們可以知道現在要取的數做貢獻要乘的係數 每次取數只能在左右兩端取 所以轉移的時候在這兩種情況中取min即可 記蒐會很方便啊 code 1 include2 include3 i...
洛谷 P1005 矩陣取數遊戲 區間dp
帥帥經常跟同學玩乙個矩陣取數遊戲 對於乙個給定的n times mn m的矩陣,矩陣中的每個元素a ai,j 均為非負整數。遊戲規則如下 每次取數時須從每行各取走乙個元素,共nn個。經過mm次後取完矩陣內所有元素 每次取走的各個元素只能是該元素所在行的行首或行尾 每次取數都有乙個得分值,為每行取數的...
洛谷 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...