P7137-[THUPC2021 初赛]切切糕【dp】
正題
題目鏈接:https://www.luogu.com.cn/problem/P7137
題目大意
有兩個人,有nnn個蛋糕,第iii個蛋糕大小為aia_iai?。
每一次第一個人可以選擇一個蛋糕把它切成任意大小的兩份(一份可以為空)。
然后第二個人有mmm次機會優(yōu)先選擇一份拿走,否則都是第一個人先拿。
兩個人都希望自己拿走的最多。
求第一個人最終能拿走多少。
1≤m≤n≤25001\leq m\leq n\leq 25001≤m≤n≤2500
解題思路
現在看來還挺簡單的,一雪前恥了屬于是。
因為是自定義順序,所以考慮起來比較麻煩所以我們先考慮怎么確定拿的順序。
瞎猜感性思考一下不難發(fā)現,如果我們把大的放在前面,那么第一個人分的時候就分太不平均,因為第二個人手里有選擇權威懾,但是如果我們把小的放在前面顯然威懾權就到第一個人手里了。因為如果第二個交了太多次機會那么第一個人后面直接全拿,所以此時第二個人不敢交這么多次機會那第一個人就可以全拿了。
所以我們直接敲定是從小到大分,那么順序固定之后就很簡單了,反過來推,設fi,jf_{i,j}fi,j?表示分到第iii時還有jjj次選擇權的第一個人總和。
那么我們就有轉移方程。
fi,j=max{min{fi?1,j?1+ai?x,fi?1,j+x}}(x∈[0,m2])f_{i,j}=max\{min\{f_{i-1,j-1}+a_i-x,f_{i-1,j}+x\}\}(x\in[0,\frac{m}{2}])fi,j?=max{min{fi?1,j?1?+ai??x,fi?1,j?+x}}(x∈[0,2m?])
考慮一下怎么確定這個xxx,其實也很簡單,設A=fi,j,B=fi,j?1A=f_{i,j},B=f_{i,j-1}A=fi,j?,B=fi,j?1?,那么顯然有B>AB>AB>A。
如果B?A≥aiB-A\geq a_iB?A≥ai?那么我們直接全拿aia_iai?這樣第二個人也不會用機會,此時fi,j=Bf_{i,j}=Bfi,j?=B。
如果B?A≤aiB-A\leq a_iB?A≤ai?那么我們把aia_iai?分給AAA不足BBB的那部分后剩下的平分給AAA和BBB,此時fi,j=B+ai?(B?A)2f_{i,j}=B+\frac{a_i-(B-A)}{2}fi,j?=B+2ai??(B?A)?。
時間復雜度:O(nm)O(nm)O(nm)
code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2510; int n,m; double a[N],f[N][N]; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lf",&a[i]);sort(a+1,a+1+n);for(int i=n;i>=1;i--){f[i][0]=f[i+1][0]+a[i];for(int j=1;j<=m;j++){double A=f[i+1][j],B=f[i+1][j-1];//B>A x<=a/2 B+x A+a-xif(B-A<=a[i])f[i][j]=B+(a[i]-B+A)/2.0;else f[i][j]=A+a[i];}}printf("%.6lf",f[1][m]);return 0; }總結
以上是生活随笔為你收集整理的P7137-[THUPC2021 初赛]切切糕【dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux从最后一行向前看(linux从
- 下一篇: CF1628A-Meximum Arra