題目鏈接
http://codeforces.com/contest/388/problem/C
題目大意
給你n堆牌, 每堆牌有m張牌, 其分數爲a1~am, 兩個人輪流選牌,第一個人只能拿最左邊的牌, 第二個人只能拿最右邊的牌(可以從不同牌堆中選), 每個人都用最優選法使自己獲得的值最大, 讓你輸出牌選完後兩個人的分數
思路
這題看似是一道很難的博弈題,但是仔細思考一下就會發現, 由於他們有隻能拿最左邊或最右邊的牌的限制,如果牌堆個數是偶數,明顯就是兩人平分, 如果是奇數個,那麼先拿的人就可以貪心地先去拿中間牌分數比較高的牌堆,就變成很簡單的博弈了
代碼
#include<bits/stdc++.h>
using namespace std;
struct P
{
int a[1005];
int v, l;
bool operator < (P& x)
{
return v < x.v;
}
}cnt1[105], cnt2[105];
int main()
{
int n, ta = 0, tb = 0;
scanf("%d", &n);
for(int i=0; i<n; ++i)
{
int m;
scanf("%d", &m);
if(m&1)
{
for(int j=0; j<m; ++j)
scanf("%d", &cnt1[ta].a[j]);
cnt1[ta].v = cnt1[ta].a[m/2];
cnt1[ta].l = m;
++ta;
}
else
{
for(int j=0; j<m; ++j)
scanf("%d", &cnt2[tb].a[j]);
cnt2[tb].l = m;
++tb;
}
}
sort(cnt1, cnt1+ta);
int ans1 = 0, ans2 = 0;
for(int i=ta-1; i>=0; --i)
{
for(int j=0; j<cnt1[i].l/2; ++j)
ans1 += cnt1[i].a[j];
for(int j=cnt1[i].l/2+1; j<cnt1[i].l; ++j)
ans2 += cnt1[i].a[j];
if((ta-i)&1) ans1 += cnt1[i].v;
else ans2 += cnt1[i].v;
//cout<<ans1<<' '<<ans2<<endl;
}
for(int i=0; i<tb; ++i)
{
for(int j=0; j<cnt2[i].l; ++j)
{
if(j < cnt2[i].l/2) ans1 += cnt2[i].a[j];
else ans2 += cnt2[i].a[j];
}
//cout<<ans1<<' '<<ans2<<endl;
}
printf("%d %d\n", ans1, ans2);
return 0;
}
反思
這種題應該把自己代入題目的角色中,再去想我該怎樣取才能使分數儘量高,有時候看似很難的博弈題可能只是一道貪心題