AB串
Time Limit:1000MS Memory Limit:32768K
Description:
对一个AB串,进行一定的操作,每次操作只能交换相邻的字符。求最少的操作数使得相同的字母都在同一边,如AAAAABBBBB。Input:
每一行给出一个AB串,长度不超过100,且A、B都含有,不含其它字符Output:
每一行一个答案,输出最少操作次数。Sample Input:
ABA
Sample Output:
1
Source:
李广为
链接:http://acm.zjut.edu.cn/ShowProblem.aspx?ShowID=1518
/* --------------------------------------------------------------------------------
WA了,原因就是中陷阱了,ABA,操作步数1,但是结果有可能有两种,ABB,BBA。。
我的代码是以ABBB这样为基础的,所以错了。。。明天再改。。下午要复习了,要考试了。。
ACM月赛也木有玩了~~~
AC,分两种情况来讨论,一种就是A左B右,一种就是B左A右,两个之中求最小的那个。。
15MS
-------------------------------------------------------------------------------- */
#include<stdio.h>
#include<string.h>
char szStr[104] ;
int nMinStep(int nStart, int nFirst , char chLeft, char chRight) ;
int main(void)
{
int i = 0 ;
int nFirstB = 0 ;
int nFirstA = 0 ;
int nMinAB = 0 ;
int nMinBA = 0 ;
int nMinTotal = 0 ;
char chTemp = 0 ;
int iA = 0 ;
int iB = 0 ;
while(scanf("%s",szStr) != EOF)
{
nMinTotal = 0 ;
nFirstB = -1 ;
nFirstA = -1 ;
i = 0 ;
while(szStr[i] != '\0')
{
if(nFirstA >= 0 && nFirstB >= 0)
{
break ;
}
else if('A' == szStr[i] && nFirstA < 0)
{
nFirstA = i ;
iA = i + 1 ;
}
else if('B' == szStr[i] && nFirstB < 0)
{
nFirstB = i ;
iB = i + 1 ;
}
i++ ;
}
nMinAB = nMinStep(iB,nFirstB,'A','B') ;
nMinBA = nMinStep(iA,nFirstA,'B','A') ;
nMinTotal = nMinAB < nMinBA ? nMinAB : nMinBA ;
printf("%d\n",nMinTotal) ;
}
return 0 ;
}
int nMinStep(int nStart, int nFirst , char chLeft, char chRight)
{
int i = nStart ;
int j = 0 ;
int nTotal = 0 ;
char szTempStr[104] ;
char chTemp ;
strcpy(szTempStr,szStr) ;
while(szTempStr[i] != '\0')
{
if(chRight == szTempStr[i])
{
i++ ;
}
else if(chLeft == szTempStr[i])
{
chTemp = szTempStr[i] ;
for(j = i ; j > nFirst ; --j)
{
szTempStr[j] = szTempStr[j-1] ;
nTotal++ ;
}
szTempStr[nFirst] = chTemp ;
nFirst++ ;
}
}
return nTotal ;
}
/* ----------------------------------------------------------------------------------------
第二种方法:
其实就是看看排前要移动的字母前面的互异字母有多少个。
比如
ABBBAA
如果A在左,B在右的话。那个在第二个A的前面有3个B,所以A最少要移动3次。同样道理排在第3个A
前面也有3个B,所以最小也要移动3次,所以这种情况下是6步。
如果B在右,A在左的话。那么排在第一个B前面有一个A,所以第一个B最少要移动1次。同样道理
第二、第三个B都至少要移动1次。所以总共是三次。
我的算法思路就是遍历一次数组,统计上述算法需要的信息。即在发现A之前,排在它前面有多少个
B或者在发现B之前,排在它前面有多少个A。
所以相对第一种算法来说,时间复杂度降低了一个常数因子,为O(n),前一种算法就算不计找到第一
个A,B,不计复制字符串的时间至少也要O(2n)的时间。
前一种算法的总时间为 :15MS
而这一种只需要: 4 MS
---------------------------------------------------------------------------------------- */
#include<stdio.h>
char szStr[104] ;
int main(void)
{
int i = 0 ;
int nFirstB = 0 ;
int nFirstA = 0 ;
int nMinAB = 0 ;
int nMinBA = 0 ;
int nMinTotal = 0 ;
int nASum = 0 ;
int nBSum = 0 ;
int fFA = 0 ;
int fFB = 0 ;
while(scanf("%s",szStr) != EOF)
{
nMinTotal = 0 ;
nFirstB = -1 ;
nFirstA = -1 ;
nMinAB = nMinBA = 0 ;
nASum = nBSum = 0 ;
fFA = fFB = 0 ;
i = 0 ;
while(szStr[i] != '\0')
{
if('A' == szStr[i])
{
if(nFirstA < 0)
{
nFirstA = i ;
nASum++;
}
else
{
nASum++ ;
}
if(nFirstB >=0)
{
nMinAB += nBSum ;
}
}
else if('B' == szStr[i] )
{
if(nFirstB < 0)
{
nFirstB = i ;
nBSum++;
}
else
{
nBSum++ ;
}
if(nFirstA >= 0)
{
nMinBA += nASum ;
}
}
i++ ;
}
nMinTotal = nMinAB < nMinBA ? nMinAB : nMinBA ;
printf("%d\n",nMinTotal) ;
}
return 0 ;
}
/* --------------------------------------------
这一个方法是建立在第二种方法上的,但是没有使用数组,所以空间复杂度应该有所下降,但是测试
结果却和有数组的一样。。。。。
而且在最后一组测试数据后面竟然木有换行符,直接EOF,所以我的代码最后还要加上一个特殊处理
时间:4MS,190K
-------------------------------------------- */
#include<stdio.h>
int main(void)
{
int nFirstB = 0 ;
int nFirstA = 0 ;
int nMinAB = 0 ;
int nMinBA = 0 ;
int nMinTotal = 0 ;
int nASum = 0 ;
int nBSum = 0 ;
int fNewLine = 1 ;
char ch = '\0' ;
while((ch = getchar()) != EOF)
{
if(1 == fNewLine)
{
nMinTotal = 0 ;
nFirstB = nFirstA = -1 ;
nMinAB = nMinBA = 0 ;
nASum = nBSum = 0 ;
}
if('\n' == ch)
{
nMinTotal = nMinAB < nMinBA ? nMinAB : nMinBA ;
printf("%d\n",nMinTotal) ;
fNewLine = 1 ;
continue ;
}
fNewLine = 0 ;
if('A' == ch)
{
if(nFirstA < 0)
{
nFirstA = 1 ;
nASum++;
}
else
{
nASum++ ;
}
if(nFirstB >=0)
{
nMinAB += nBSum ;
}
}
else if('B' == ch)
{
if(nFirstB < 0)
{
nFirstB = 1 ;
nBSum++;
}
else
{
nBSum++ ;
}
if(nFirstA >= 0)
{
nMinBA += nASum ;
}
}
}
/*加上这一行是因为,那个最一个测试数据后面竟然不加换行符...*/
nMinTotal = nMinAB < nMinBA ? nMinAB : nMinBA ;
printf("%d\n",nMinTotal) ;
return 0 ;
}