CF388C-Fox and Card Game【博弈論,結論】
阿新 • • 發佈:2021-10-14
正題
題目連結:https://www.luogu.com.cn/problem/CF388C
題目大意
有\(n\)堆卡片,第\(i\)堆有\(s_i\)張,給出每張卡的權值。現在先手選擇一堆取走堆底的牌,然後後手選擇一堆取走堆頂的牌,直到所有牌被取走。在雙方都要求最大化取走的牌的權值的情況下求先後手的權值。
\(1\leq n,s_i\leq 100,1\leq a_{i,j}\leq 1000\)
解題思路
大膽猜測結論是每堆牌都是先後手各自取走約一半的牌,因為如果總和固定最大化自己就相當於最小化對方。
如果存在一種情況後手和先手各自取不同的堆,那麼這肯定是對後手優的,又因為權值一樣,也就是對先手劣的,與對先手和後手都優衝突。
現在偶數個數的都是平分的,主要考慮奇數,對於奇數來說就是先手取走中間那個然後交換先後手。
直接把奇數兩邊的平分,然後拿中間出來排序,先後手依次取走即可。
時間複雜度:\(O(ns)\)
code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=110; int n,s,sum,ans,m,a[N],r[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&s); for(int j=1;j<=s;j++) scanf("%d",&a[j]),sum+=a[j]; if(s&1){ ++m; for(int j=1;j<=s/2;j++)ans+=a[j]; for(int j=s/2+2;j<=s;j++)ans-=a[j]; r[m]=a[s/2+1]; } else{ for(int j=1;j<=s/2;j++)ans+=a[j]; for(int j=s/2+1;j<=s;j++)ans-=a[j]; } } sort(r+1,r+1+m); reverse(r+1,r+1+m); for(int i=1;i<=m;i++) if(i&1)ans+=r[i]; else ans-=r[i]; printf("%d %d\n",int(sum/2.0+ans/2.0),int(sum/2.0-ans/2.0)); return 0; }