帥帥經常跟同學玩乙個矩陣取數遊戲:對於乙個給定的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複製1 2 3
3 4 2
82noip 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 ...