蓝桥杯基础训练1573:完美的代价(C语言实现)
蓝桥杯基础训练1573:完美的代价(C语言实现)
解析:本题妙用了————贪心(如果不了解可以直接看下面的举例)
如图:
由此开始,先定义i,k,两个变量,i 从字符串最左边开始往右遍历,k则从最右边开始往左遍历
i 先不改变,让k自减往左遍历(k - -),如果a[ i ] 和 a[ k ]不一样,则k继续往左遍历,直到和a[ i ]一样,如下
定义一个变量 j 等于字符长度(可以理解为一直指最后一个未经过交换对称的字符),则下标最大可到 j-1
则将a[ k ]移动到于a[ i ]对称的位置,可以通过a[ k ] = a[ k+ 1]进行交换,条件为k < j , 最后 a[ j ] = a[ i ]即可,并且在此过程,可以定义一个记录交换次数的变量sum=0,每次交换都进行自增(sum++),由于交换放置后的字符已经形成对称,所以无需改变其位置,下一次下一组字符的交换无需到达该位,可以让 j = j - 1,如下 ,j 原指a,a已经是交换对称了,可以忽略,j指向前一个,i++,接下来只需考虑红框内的字符数组,交换好的无需再管。
每一轮都让k==j,这保证了k每次都从未经对称的末尾字符开始往左遍历,接下来k遇到m,然后交换,a[ k ] = a[ k+1] ,条件为k < j,最后a[ j ] == a[ i ]即可,和上一步一样的方法,以此类推。
但是,如果一直找不到相等的字符,怎么办?
像这种情况,如果一直找不到相同的,最后会遇到 i==k 的情况,当i == k的时候,我们可以知道 a[ i ]在数组内独一无二,我们是不是可以把它移动到中间,共移动(数组长度/2 - i)次,这个时候可以不需要真的进行交换,并无影响结果(因为独一无二数放在中间后,由于是经过对称移动的,所以并不能动其位置,所以可以忽略,就和没移动一个样,交换的时候也要跳过,因此不必进行这一交换步骤)。
如果出现两次 i = = j的情况,则代表数组内存在两个独一无二的字符,不可能存在完美列,可以结束程序,打印Impossible,
当条件 i < j 不满足的时候,代表对称交换已经执行完毕,可以输出sum总值。
代码如下:
#include <stdio.h> #include <stdlib.h> int main(void) { char a[8001]; bool flag = false; int n, sum=0; scanf("%d", &n); getchar(); gets(a); int i, j, k, m; j = n - 1; for(i=0; i<j; ++i) for(k=j; k>=i; --k) { if(i==k) { if(n%2==0) { printf("Impossible"); return 0; } else { if(flag) { printf("Impossible"); return 0; } } sum += n/2-i; flag = true; break; } if(a[i]==a[k]) { for(m=k; m<j; ++m) { a[m] = a[m+1]; sum++; } a[j] = a[i]; --j; break; } } printf("%d", sum); return 0; }
如有不足,请多指教,欢迎评论区留言O(∩_∩)O
阅读更多- 蓝桥杯 基础训练 完美的代价-----------------------------C语言——菜鸟级
- 蓝桥杯 基础训练 完美的代价(转)
- 蓝桥杯 - 算法训练 学做菜 C语言实现
- 蓝桥杯 基础练习 完美的代价
- 蓝桥杯 BASIC-19 基础练习 完美的代价(有贪心特点)
- 蓝桥杯 - 算法训练 接水问题 C语言实现
- 蓝桥杯:基础训练——/* 问题描述: 基础练习 完美的代价 时间限制:1.0s 内存限制:512.0MB 问题描述 回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为
- 1573:基础练习 完美的代价
- 蓝桥杯 基础练习 完美的代价
- 蓝桥杯 基础练习 完美的代价
- 蓝桥杯 - 算法训练 寂寞的数 C语言实现
- 蓝桥杯 - 算法训练 - 移动小球 C语言实现
- 蓝桥杯 - 算法训练 数的划分 C语言实现
- 蓝桥杯 - 算法训练 黑白无常 C语言实现
- 蓝桥杯 - 算法训练 蜜蜂飞舞 C语言实现
- 蓝桥杯 基础练习 完美的代价
- 蓝桥杯 - 算法训练 - 铁轨 栈 C语言实现
- 蓝桥杯 基础练习 完美的代价 【贪心 + string】
- 蓝桥杯 - 算法训练 删除多余括号 C语言实现
- 蓝桥杯 - 算法训练 暗恋 C语言实现