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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章