题目:[蓝桥杯]翻硬币。算法:递推

1428: [蓝桥杯]翻硬币
时间限制: 1 Sec 内存限制: 256 MB
提交: 51 解决: 39
[状态] [提交] [命题人:外部导入]
题目描述
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:oo*oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作
输入
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
输出
一个整数,表示最小操作步数
样例输入 Copy

**********

o****o****

样例输出 Copy
5

好嘞,我们先来看一下题目的意思:
使硬币翻最少次数,使初始状态的排列变为目标状态
其中有一条规则非常重要,就是,翻动一个硬币时,相邻的另一个硬币也会跟着翻转
这样,影响一个硬币的状态的原因就会有三个,左边的、右边的、和他自己这是一个硬币是否翻转的决定性因素
我们拿下面的这个例子来看
题目:[蓝桥杯]翻硬币。算法:递推_第1张图片
我们发现,有两类方式来翻硬币,一:翻了前面的,后面跟着翻;二是:翻了后面的,前面的跟着翻
以此我们得到了四种翻硬币的方法,但是我们会发现,左面的两种方法,和右面的两种方法得到的结果时一样的。那么我们将这两种方式都使用就会很多余,毕竟两种方式的到的结果都是相同的嘛!
那么我们不妨选择左面的翻转规则,即翻转前一个硬币,后面一个硬币也会跟着翻转。
(这是确定规则,简化问题)

解决了这个问题,下面的内容就很简单了。下面我们还是拿样例来说事
按照使用for循环的尿性, 按照一般的做题方式,我们从第一个硬币开始考虑,如果第一个现有状态和目标状态不匹配,就翻转一下第一个和第二个,然后再看第二个的状态是怎么样的,再决定是不是要翻转,并依次向下推。
我们来模拟一下样例吧!
题目:[蓝桥杯]翻硬币。算法:递推_第2张图片
分析到这里,要注意的点都分析好了
下面为大家呈上代码:

#include 
#include 
#include 
#include 
#include 

using namespace std;

string s, str;
//定义一个函数,翻转当前的位置
void turn(int i){
     //传入的数字为需要翻转的位置
	if (s[i] == '*') s[i] = 'o';
	else s[i] = '*';
}
int main(){
     
	cin >> s >> str;//s是初始状态,str是要达到的目标状态
	
	int res = 0;//表示操作几次
	for (int i = 0; i < s.size(); i ++ )
		if (s[i] != str[i]){
     //如果当前状态和目标状态不同
			res ++;
			turn(i);turn(i + 1);
		}
		
	cout << res << endl;//输出结果
	
	return 0;
} 

最后再补充一句,main函数里的那个#turn(i) 是可以不写的,
因为再if的条件判断后,第i个位置已经影响不到第i+1个位置了

为了写这个题解,已经奋战了三个小时了,如果觉得帮到了大家,点个咱再走呗

你可能感兴趣的:(#,蓝桥杯C++AB组)