日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

*【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流)

發布時間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 *【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

You may have heard of the pie rule before. It states that if two people wish to fairly share a slice of pie, one person should cut the slice in half, and the other person should choose who gets which slice. Alice and Bob have many slices of pie, and rather than cutting the slices in half, each individual slice will be eaten by just one person.

The way Alice and Bob decide who eats each slice is as follows. First, the order in which the pies are to be handed out is decided. There is a special token called the "decider" token, initially held by Bob. Until all the pie is handed out, whoever has the decider token will give the next slice of pie to one of the participants, and the decider token to the other participant. They continue until no slices of pie are left.

All of the slices are of excellent quality, so each participant obviously wants to maximize the total amount of pie they get to eat. Assuming both players make their decisions optimally, how much pie will each participant receive?

Input

Input will begin with an integer?N?(1?≤?N?≤?50), the number of slices of pie.

Following this is a line with?N?integers indicating the sizes of the slices (each between?1?and?100000, inclusive), in the order in which they must be handed out.

Output

Print two integers. First, the sum of the sizes of slices eaten by Alice, then the sum of the sizes of the slices eaten by Bob, assuming both players make their decisions optimally.

Examples

Input

3 141 592 653

Output

653 733

Input

5 10 21 10 21 10

Output

31 41

Note

In the first example, Bob takes the size?141?slice for himself and gives the decider token to Alice. Then Alice gives the size?592?slice to Bob and keeps the decider token for herself, so that she can then give the size?653?slice to herself.

題目大意:

有一個長度為N的權值數組,兩個人A,B。定義一種權力X為:決定當前這個數組元素分給誰。下次權利X授予沒有分得前一個元素的人。如,現在A有權力,將當前數組元素分給自己,那么下一次權力X將被B獲得。如果A將數組元素分給B,那么A繼續擁有這個權利。一開始權利在A手中,每個人都會采取對自己最有利的方式分配。問最后兩個人各自的權值總和。

解題報告:

考慮dp求解,要明確dp的狀態只與是否有令牌有關,而與令牌在誰手里無關。因為不論令牌在誰手里,那個人都會盡可能的獲得最大的物品價值。

因此我們用dp[i]表示第i個物品開始分配,當前有令牌的人能獲得的最大物品價值,然而因為我們只知道初始有令牌的是Bob,因此我們要逆推:?dp[i] = max(dp[i + 1], sum[i + 1] - dp[i + 1] + val[i]) //?max(不要當前物品, 要)

其實相當于是你如果要從前往后推的話,需要關注令牌是否是同一個人拿著的,所以麻煩很多,而逆推就簡單很多,因為令牌是往后傳的,我們當前是有令牌的,所以下一個令牌給誰,是我們決定的,就比較好寫。

最后dp[1]就是Bob獲得的價值了。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; ll dp[MAX],a[MAX],sum[MAX]; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%lld",a+i);for(int i = n; i>=1; i--) sum[i] = sum[i+1] + a[i];for(int i = n; i>=1; i--) {dp[i] = max(dp[i+1],a[i] + (sum[i+1] - dp[i+1]));//不選,選 }printf("%lld %lld\n",sum[1] - dp[1],dp[1]);return 0 ;}

錯誤代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; ll a[MAX],sum[MAX]; ll dp[MAX][2][2];//dp[i][j][k]代表第i個數并且第i個選沒選0/1,令牌在 0/1(Bob)手里的最大值 ,Bob獲得的最大值 int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%lld",a+i);for(int i = 1; i<=n; i++) sum[i] = sum[i-1] + a[i];dp[1][1][1] = a[1];dp[1][0][1] = 0;for(int i = 2; i<=n; i++) {dp[i][0][0] = a[i] + max(dp[i-1][1][1] , dp[i-1][0][0]);//sum[i-1] - min(dp[i-1][1][1] , dp[i-1][0][0]);dp[i][0][1] = max(dp[i-1][1][0] , dp[i-1][0][1]);dp[i][1][0] = dp[i][0][0];dp[i][1][1] = dp[i][0][1] + a[i];}ll maxx = 0;maxx = max(maxx,dp[n][0][0]);maxx = max(maxx,dp[n][0][1]);maxx = max(maxx,dp[n][1][0]);maxx = max(maxx,dp[n][1][1]);printf("%lld %lld\n",sum[n] - maxx,maxx);return 0 ;} //適用于:可以選擇要或者不要,但是不要的話不會把分數給對方 的方法。 // for(int i = 2; i<=n; i++) { // dp[i][0][0] = max(dp[i-1][1][1] , dp[i-1][0][0]);//sum[i-1] - min(dp[i-1][1][1] , dp[i-1][0][0]); // // dp[i][0][1] = max(dp[i-1][1][0] , dp[i-1][0][1]); // dp[i][1][0] = dp[i][0][0]; // dp[i][1][1] = dp[i][0][1] + a[i]; // }

想到這個狀態感覺可以就開始寫了, 但是有個問題啊,,這是個博弈dp,也就是說你不能只顧著Bob,所以這樣dp是錯誤的,因為對方也是用的最優決策你要知道這一點,所以就不太對。所以對于這種博弈dp,我們需要關注的是令牌,因為誰拿著令牌,誰就希望得到最優解。所以我們應該直接設定狀態為dp[i]為拿著令牌的人第i輪選擇到最后可以得到的最優解。

為什么倒著呢?因為這是求最優解問題,就跟數塔一樣,先考慮最后一步決策,然后倒著推。如果是計數,那就一般正著寫。

(其實貌似也是可以寫的?就是比較麻煩,你考慮令牌不在Bob手里的時候求的是Bob拿到的最小值 就行了吧?)

改了改但還是放棄了、、、

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; ll a[MAX],sum[MAX]; ll dp[MAX][2][2];//dp[i][j][k]代表第i個數并且第i個選沒選0/1,令牌在 0/1(Bob)手里的最大值 ,Bob獲得的最大值 int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%lld",a+i);for(int i = 1; i<=n; i++) sum[i] = sum[i-1] + a[i];dp[1][1][1] = a[1];dp[1][0][1] = 0;for(int i = 2; i<=n; i++) {dp[i][0][0] = a[i] + sum[i-1]/*sum[i]*/ - max(sum[i-1] - dp[i-1][1][1] , sum[i-1] - dp[i-1][0][0]);//sum[i-1] - min(dp[i-1][1][1] , dp[i-1][0][0]);dp[i][0][1] = max(dp[i-1][1][0] , dp[i-1][0][1]);dp[i][1][0] = dp[i][0][0] - a[i];dp[i][1][1] = dp[i][0][1] + a[i];}ll maxx = 0;maxx = max(maxx,dp[n][0][0]);maxx = max(maxx,dp[n][0][1]);maxx = max(maxx,dp[n][1][0]);maxx = max(maxx,dp[n][1][1]);printf("%lld %lld\n",sum[n] - maxx,maxx);return 0 ;} /* 3 10 20 40 30 40 */

?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的*【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。