Codeforces Round #228 (Div. 1)C. Fox and Card Game

題目鏈接

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;
}

反思

這種題應該把自己代入題目的角色中,再去想我該怎樣取才能使分數儘量高,有時候看似很難的博弈題可能只是一道貪心題

發佈了54 篇原創文章 · 獲贊 13 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章