蓝桥杯 ALGO-128 Cowboys

题目:简单说就是字符串中如果出现AB这样连着的字符,就要变成BA,而且此题要把字符串看成一个环形的来看

思路:使用动态规划解决,dp[i][0],表示第i个节点没发生变化,dp[i][1],第j个第i个节点发生了变化。首先分析一下几种情况

①当前节点为B,前面一个为A,即为AB,可以由ABB变化得来,还有就是BA变化不可能变化得到AB,可能会有老哥说存在(AAB->ABA这种情况是后面的B调整得到的,现在只考虑当前节点以及前面的节点,所以不考虑此情况),所以我们认为当前B是不会变化的,即dp[i][1] = 0,而B状态不变化则由前面的A决定,即dp[i][1] = dp[i-1][0] + dp[i-1][1];

②当前节点为A,前面一个为B,即为BA,当前的BA可以是有AB转化而来,也可以是没有变化,如果是没有变化的话,前面的B也没变化,即dp[i][0] = dp[i-1][0];如果变化的话,B也随之变化,主要是由B前面的情况决定,即dp[i][1] = dp[i-2][0] + dp[i-2][1];

③前后都相同,即为AA或者BB,则一定没有变化,即dp[i][1] = 0;没变化的情况主要是有前面的情况决定,即dp[i][0] = dp[i-1][0] +dp[i-1][1]; 

如果都是A或者B,则直接返回1,否则一定可以找到第一个BA的(因为我们是把一个字符串看成一个环形考虑的),把此BA作为一个整体,设当前的B的位置为pos,那么,将从pos+2到pos-1进行判断,如果碰到BA一定是有AB转化得到的,那么会把除BA的全部都判断出来,而BA需要第二个函数判断,即BABA、BABABA这样的情况

看了几个大佬的代码总结的;

参考一:https://blog.csdn.net/lmhacm/article/details/79723475

参考二:https://blog.csdn.net/survivorone/article/details/54236211

参考三:https://blog.csdn.net/qq_39574690/article/details/75933124

代码:

#include<iostream>
#include<string.h>
#define N 110
using namespace std;
int dp[N][2],len;//len用于环形处理时使用 
char s[N];//保存字符串 
int judge1(int st,int en){
	dp[st][0] = 1;//第一个是不变的, 
	dp[st][1] = 0; 
	while(st!=en){
		st = (st+1)%len;
		if(s[st]-1 == s[(st-1+len)%len]){//当前为B,前面一个为A,AB,可以有ABB得到,BA得不到AB的,看出B不变 
			dp[st][0] = dp[(st-1+len)%len][1];//B不变的情况由前面A的变化决定 
			dp[st][1] = 0;//由于当前的B不变,所以为0 
		}else if(s[st]+1 == s[(st-1+len)%len]){//当前为A,前面一个为B,BA
			dp[st][0] = dp[(st-1+len)%len][0];//A不变,那么前面的B也不变 
			dp[st][1] = dp[(st-2+len)%len][0] + dp[(st-2+len)%len][1];//A变化的话,B也会跟着变化,由B前面决定 
			if(dp[st][1] == 0){//如果位于开始的位置的话,就直接设置为1 
				dp[st][1] = 1; 
			} 
		}else{//当前与前面的相同 
			dp[st][0] = dp[(st-1+len)%len][0] + dp[(st-1+len)%len][1];//如果变化的话,就由前面总的决定 
			dp[st][1] = 0;//如果相同的话,就不会变化,故1为0 
		} 
	} 
	return dp[st][0] + dp[st][1];//由开始的两种情况决定 
} 
int judge2(int st,int en){
	int length = 2;//表示最初的BA两个符号
	if(s[st] == 'B'){
		if(s[(st+1)%len] =='A'){//为BA此情况
			st = (st+2)%len;
			length += 2;
		}else{//为BB此情况 
			return 0;
		}
	} 
	if(s[en] == 'A'){
		if(s[(en-1+len)%len == 'B']){//为AB 
			en = (en-2+len)%len;
			length += 2;
		}else{//为AA 
			return 0;
		}
	} 
	if(length >= len) {//判断是否为BABA、BABABA这样的情况,judge把除一开始的BA变化的都计算了.还有加上它变化的 
		return 1;
	} 
	memset(dp,0,sizeof(dp));//如果不是BABA这些情况,就要在判断一次  
	dp[st][0] = 1;//第一个是不变的, 
	dp[st][1] = 0; 
	while(st!=en){
		st = (st+1)%len;
		if(s[st]-1 == s[(st-1+len)%len]){//当前为B,前面一个为A,AB,可以有ABB得到,BA得不到AB的,看出B不变 
			dp[st][0] = dp[(st-1+len)%len][1];//B不变的情况由前面A的变化决定 
			dp[st][1] = 0;//由于当前的B不变,所以为0 
		}else if(s[st]+1 == s[(st-1+len)%len]){//当前为A,前面一个为B,BA
			dp[st][0] = dp[(st-1+len)%len][0];//A不变,那么前面的B也不变 
			dp[st][1] = dp[(st-2+len)%len][0] + dp[(st-2+len)%len][1];//A变化的话,B也会跟着变化,由B前面决定 
			if(dp[st][1] == 0){//如果位于开始的位置的话,就直接设置为1 
				dp[st][1] = 1; 
			} 
		}else{//当前与前面的相同 
			dp[st][0] = dp[(st-1+len)%len][0] + dp[(st-1+len)%len][1];//如果变化的话,就由前面总的决定 
			dp[st][1] = 0;//如果相同的话,就不会变化,故1为0 
		} 
	} 
	return dp[st][0] + dp[st][1];//由开始的两种情况决定 
} 
int main(){
	int i;
	scanf("%s",s);
	len = strlen(s);
	memset(dp,0,sizeof(dp));//全部初始化为0
	for(i=0;i<len;i++){//找到BA这样的,返回的i是当前B的位置 
		if(s[i]-1 == s[i+1]){
			break;
		}
	} 
	int begin = (i+2)%len , end = (i-1+len)%len;//先不考虑BA这两个 
	cout<< judge1(begin,end) + judge2(begin,end);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值