沒錯 本齟齬又來水題解了
題目鏈結
給你乙個大小為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.每次取數都有乙個得分值,為每行取數的得分之和,每行取數的得分...