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