CF 997A Convert to Ones - 贪心、模拟

CF997A Convert to Ones

题目链接:【洛谷】 CF997A Convert to Ones

算法标签: 字符串贪心模拟

题目

题目描述

给你一个长度为 n 的01串($ n \leq 3*10^5 $),你有两种操作:

1.将一个子串翻转,花费 X

2.将一个子串中的0变成1,1变成0,花费 Y

求你将这个01串变成全是1的串的最少花费。

输入格式

第一行,三个整数\(n\)\(x\)\(y\),分别代表字符串长度、翻转字串的花费、修改字串的花费。

第二行,为一个长度为\(n\)的字符串。

输出格式

共一行,为所求的最小花费。

输入输出样例

输入 #1

5 1 10
01000

输出 #1

11

输入 #2

5 10 1
01000

输出 #2

2

输入 #3

7 2 3
1111111

输出 #3

0

题解:

想法很巧妙,可以定位为一道思维题,大致的思路就是贪心(不确定)。

由于一个01串,假设为\(011111000001\) ,在这道题的题目下可以很简单的处理为\(0101\)这样一个串,在进行两种操作取最小值。

仔细分析这两种操作的时候,我们可以得到以下结论:

1 我们可以将所有中操作找出两种最优的:

a. 将0放在一边,1放在一边,最终一次转换 

b. 每一个都单独转换

2 将字符串第0位设为一个1,这样我们只需要统计由某一位为0而前一位为1的个数,这样的答案就是操作的总次 数(可以推得无论如何进行操作总次数都一致)。而且我们可以发现无论如何进行操作,最后一次都是转换, 所以我们可以得出

\(ans = (cnt - 1) * min(x, y) + y;\)

由此此题得解,注意本题数据需要开long long。

下面附上AC代码

AC代码

#include <bits/stdc++.h>

using namespace std;

const int N  = 300030;

typedef long long ll;

ll n, x, y, cnt;
char num[N];

int main()
{
    scanf("%d%d%d", &n, &x, &y);
    scanf("%s", num + 1);
    num[0] = '1';
    for (int i = 1; i <= n; i ++ )
    {
        if (num[i] == '0' && num[i - 1] == '1')
            cnt ++ ;
    }
    if (cnt == 0)
        printf("0");
    else
    {
        ll ans = (cnt - 1) * min(x, y) + y;
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/littleseven777/p/11845641.html