【acm结论】有序排列0101交替排列

本题的例题来自UESTC的OJ1514,Little_Pro的driver朋友们和他的魔法。

题意概述:

第一行输入一个整数n(1~100000),第二行输入长度为n的,有且只有0和1组成字符串

现有两种操作:

操作a:交换相邻的两个数的值

操作b:更改某个位置的值

请问:最少需要多少次操作才可以使得该字符串以0和1交替出现的顺序出现。

题意分析:

题意得意思是对于任意得字符串,最终得输出序列有两种,要么为010101······,要么为101010······,那么分析到这里,我们就应该知道该这个字符串应该分别输出以上两个目标序列,并将最小次数操作进行比较,输出其中得较小值。

这也是一种贪心

那么我们怎么利用计算机使用操作a,b来操作字符串呢?换句话说,我们怎么知道在一处不满足0和1交替排列得地方是使用操作a还是操作b?

有人可能会说if条件语句判断。

其实当你写完判断程序之后,你会发现,这道题与判断操作无关

我们首先要意识到1和0交替排列意味着序列得奇数位和偶数位上的值是一样的。(1010···或0101···)

其次因为操作a只影响相邻得两个数,而操作b只影响一个数。即对于每个操作一次都只能处理一个奇数位(或偶数位),而不能处理两个奇数位(或偶数位)。

代码思路

对于两种输出序列

1:0101010······

2:1010101······

那么我们先对输入的字符串对两种序列分别讨论。

第一组情况下,对数组遍历,声明a1为奇数位值上位1的数量,声明a2为偶数位值上位0的数量,

第二组情况下,对数组遍历,声明a3为奇数位值上位0的数量,声明a4为偶数位值上位1的数量,

然后每种的情况下,达到0和1交替出现的最小操作次数是max(a1,a2)和max(a3,a4),那么所求量的答案就呼之欲出了,就是min(max(a1,a2),max(a3, a4))。

代码


int main()
{
	int n, sum1 = 0,sum2=0;
	int a1=0, a2=0, a3=0, a4=0;
	cin >> n;
	getchar();
	for (int i = 0; i < n; i++)
	{
		scanf("%c", &num[i]);
	}
	getchar();
	for (int i = 0; i < n; i++)//第一种
	{
		if ( i % 2 == 1) 
		{
			if (num[i] != '0') a2++;
		}
		else 
		{
			if (num[i] != '1') a1++;
		}
	}
	for (int i = 0; i < n; i++)//第二种
	{
		if (i % 2 == 0)
		{
			if (num[i] != '0') a3++;
		}
		else
		{
			if (num[i] != '1') a4++;
		}
	}
	sum1 = max(a1, a2);
	sum2 = max(a3, a4);
	if(sum1<sum2)
		printf("%d", sum1);
	else
		printf("%d", sum2);
	return 0;
}

代码仅供参考哦!

如果你觉得对你有帮助的话,请给作者一个赞吧QTQ。

我会把你的赞当作我前进的动力,继而不懈的继续前行!!!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星星也倦了/

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值