本题的例题来自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;
}
代码仅供参考哦!