洛谷 P1005 矩陣取數遊戲

2021-10-25 17:54:05 字數 3808 閱讀 5243

沒錯 本齟齬又來水題解了

題目鏈結

給你乙個大小為n*m的矩陣,你將進行m次操作,每次操作可以拿矩陣中每一行兩端的其中乙個數字,每個數字只能拿一次。拿乙個數字的貢獻為該數字的權值val×2^i(這個數是在第i次操作被拿走的),然後問在m次操作後最大貢獻和為多少。

這道題就很像乙個執行了n次的區間取數問題,那麼我們可以用區間dp去解決。

dp[i][j] 中的i表示區間左端點,j表示區間又端點,dp[i][j] 整體表示當區間被取到 [i, j] 的時候的最優解。

那麼我們看看怎麼樣寫轉移方程

因為區間 [i, j] 這個狀態只能由 [i-1, j] 取走了左端點或者區間 [i, j+1] 取走了右端點才能到達,所以我們轉移方程應該是:

(val[i]為i點的貢獻值)

dp[i]

[j]=

max(dp[i-1]

[j]+ val[i]

, dp[i]

[j+1

]+ val[j]

);

但是這道題的資料範圍是 [1, 80] , 2^80次方太大了,所以我們需要用大數取模擬這個過程。

大數模板

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define pi acos(-1)

#define inf 0x3f3f3f3f

#define pii pair

#define fi first

#define se second

#define l_son node<<1

#define r_son node<<1|1

#define mp(a, b) make_pair(a, b)

#define piii pair

#define uf(a, b, i) for (register int i = (a); i <= (b); ++i)

#define df(a, b, i) for (register int i = (a); i >= (b); --i)

#define maxn 9999

#define maxsize 10

#define dlen 4

using

namespace std;

inline

intread()

while

(ch >=

'0'&& ch <=

'9')

return x * f;

}template

<

class

t>

inline

void

print

(t x)

template

<

class

t>

t max

(t a, t b)

template

<

class

t>

t min

(t a, t b)

const ll mod =

1e9+7;

class

bignum

bignum

(const

int)

;//將乙個int型別的變數轉化為大數

bignum

(const bignum &);

//拷貝建構函式

bignum &

operator=(

const bignum &);

//過載賦值運算子,大數之間進行賦值運算

friend istream&

operator

>>

(istream&

, bignum&);

//過載輸入運算子

friend ostream&

operator

<<

(ostream&

, bignum&);

//過載輸出運算子

bignum operator+(

const bignum &

)const

;//過載加法運算子,兩個大數之間的相加運算

bignum operator*(

const bignum &

)const

;//過載乘法運算子,兩個大數之間的相乘運算

bool

operator

>

(const bignum & t)

const

;//大數和另乙個大數的大小比較};

bignum::

bignum

(const

int b)

a[len++

]= d;

}bignum::

bignum

(const bignum & t)

:len

(t.len)

bignum & bignum::

operator=(

const bignum & n)

istream&

operator

>>

(istream & in, bignum & b)

b.a[count]

=sum;

count++;}

b.len =count++

;return in;

}ostream&

operator

<<

(ostream& out, bignum& b)

return out;

}bignum bignum::

operator+(

const bignum & t)

const}if

(t.a[big]!=0

) t.len = big +1;

else

t.len = big;

return t;

}bignum bignum::

operator*(

const bignum & t)

const

else}if

(up !=0)

ret.a[i + j]

= up;

} ret.len = i + j;

while

(ret.a[ret.len -1]

==0&& ret.len >1)

ret.len--

;return ret;

}bool bignum::

operator

>

(const bignum & t)

const

else

return

false;}

bignum quick_pow

(int pow)

return ans;

}int n, m;

int rec[82]

[82];

bignum dp[82]

[82];

bignum f[82]

;void

scan()

void

work()

}}ans = ans + maxn;

} cout << ans << endl;

}int

main()

洛谷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 ...

洛谷P1005 矩陣取數遊戲

帥帥經常跟同學玩乙個矩陣取數遊戲 對於乙個給定的n m的矩陣,矩陣中的每個元素aij均為非負整數。遊戲規則如下 1.每次取數時須從每行各取走乙個元素,共n個。m次後取完矩陣所有元素 2.每次取走的各個元素只能是該元素所在行的行首或行尾 3.每次取數都有乙個得分值,為每行取數的得分之和,每行取數的得分...