码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 73 (Rated for Div. 2)

时间:2020-04-06 09:56:10      阅读:53      评论:0      收藏:0      [点我收藏+]

标签:元素   启示   amp   直接   perfect   href   ++   scan   class   

题目链接:https://codeforces.com/contest/1221

A - 2048 Game

随便搞搞。

B - Knights

题意:在一个n*n的棋盘中,每个格子放一个黑马或者白马。求一种放置方案使得互相攻击的异色马最多。

题解:奇偶染色。

C - Perfect Team

题意:有c个代码手,有m个口胡怪,有x个倒水哥。要求组成尽可能多的三人队,每个三人队至少有一个代码手和一个口胡怪。

题解:首先先把1:1:1的队伍尽可能配出来,这时如果用完了代码手或者口胡怪,就得到了答案。否则是用完了倒水哥。那么两种极端的情况分别是:全部都是2个代码手配1个口胡怪,全部都是1个代码手配2个口胡怪,这两种直接算出来,剩下的总是有办法配出尽可能多的三人队。

void TestCase() {
    ll c, m, x;
    scanf("%lld%lld%lld", &c, &m, &x);
    ll ans = 0;
    ll tmp = min(c, m);
    if(x >= tmp)
        ans += tmp;
    else {
        ans += x;
        c -= x;
        m -= x;
        tmp = min(c, m);
        if(c >= 2 * m)
            ans += m;
        else if(m >= 2 * c)
            ans += c;
        else
            ans += (m + c) / 3;
    }
    printf("%lld\n", ans);
}

事实上,只需要把c和m强制变成相等,多出来的那些都算作是倒水哥就可以了。

D - Make The Fence Great Again

题意:有一个n个数的数组,把第i个数字ai增加1的代价为bi,可以对任意元素增加任意次。求最小的花费使得整个数组没有临位相同。

题解:看起来只有“临位相同”一个制约条件,那么感觉就是一个dp,而且情况还不多。

猜想:每个元素其实最多被增加1次。

设dp[i][j]表示已经完成前i个元素,且第i个元素增加j次的总花费。

那么:dp[1][0]=0,dp[1][1]=b[1],这个非常简单。后面的会用到吗?

那么:dp[2][0]=?,若a[1]=a[2],那么只能从dp[1][1]转移,并且显然没有必要从dp[1][2]转移,若a[1]+1=a[2],那么显然只能从dp[1][0]转移,并且显然dp[2][2]也没有意义;dp[2][1]=?,若a[1]=a[2],同理从dp[1][0]转移,若a[1]=a[2]+1,同理从dp[1][1]转移。所以猜想好像是对的?第一个样例都过不了!

但是这个貌似还是有启示,会不会每个元素最多被增加5次呢?

int a[300005], b[300005];
ll dp[300005][6];

void TestCase() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d%d", &a[i], &b[i]);
    for(int j = 0; j <= 5; ++j)
        dp[1][j] = 1ll * j * b[1];
    for(int i = 2; i <= n; ++i) {
        for(int j = 0; j <= 5; ++j)
            dp[i][j] = LINF;
        for(int j = 0; j <= 5; ++j) {
            for(int k = 0; k <= 5; ++k) {
                if(a[i - 1] + k == a[i] + j)
                    continue;
                dp[i][j] = min(dp[i][j], dp[i - 1][k] + 1ll * j * b[i]);
            }
        }
    }
    ll ans = LINF;
    for(int j = 0; j <= 5; ++j)
        ans = min(ans, dp[n][j]);
    printf("%lld\n", ans);
}

通过了,这……

事实上我觉得很有可能最多只会增加2次(因为相邻3个数最多只会占3个连续的位置)。

int a[300005], b[300005];
ll dp[300005][3];

void TestCase() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d%d", &a[i], &b[i]);
    for(int j = 0; j <= 2; ++j)
        dp[1][j] = 1ll * j * b[1];
    for(int i = 2; i <= n; ++i) {
        for(int j = 0; j <= 2; ++j)
            dp[i][j] = LINF;
        for(int j = 0; j <= 2; ++j) {
            for(int k = 0; k <= 2; ++k) {
                if(a[i - 1] + k == a[i] + j)
                    continue;
                dp[i][j] = min(dp[i][j], dp[i - 1][k] + 1ll * j * b[i]);
            }
        }
    }
    ll ans = LINF;
    for(int j = 0; j <= 2; ++j)
        ans = min(ans, dp[n][j]);
    printf("%lld\n", ans);
}

启示:就算猜想是错的,好像也可以得到一些思路,大胆猜想。

Educational Codeforces Round 73 (Rated for Div. 2)

标签:元素   启示   amp   直接   perfect   href   ++   scan   class   

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12640383.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!