题目详情
给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如
- 有ab或ba连续出现,你把它们替换为字母c;
- 有ac或ca连续出现时,你可以把它们替换为字母b;
- 有bc或cb 连续出现时,你可以把它们替换为字母a。
你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。
输入:字符串。长度不超过200,仅由abc三种小写字母组成。
输出: 按照上述规则不断消除替换,所得到的字符串最短的长度。
例如:输入cab,输出2。因为我们可以把它变为bb或者变为cc。
输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。
以下是我的思路:
首先需要明白的是
1.结束状态是只剩下一种字符,此时字符串的长度就是答案;
2.结束状态的前一状态到结束状态的转换是其他两种字符转换为另一字符(结果剩余字符)
我们要想获得的结果字符串的长度最短,需要每次转换的是数量较多的两种字符(如果不存在这样的相邻字符,那么必定存在数量最多和第三多的相邻字符,将其转换为第二种多的字符),重复此过程知道只剩下一种字符为止。(结束状态的前一状态中数量最多的字符是最后结果中的剩余字符,通过这样可以理解为什么每次消除的是最多两种,当然是存在这两种字符的相邻组合的情况下)
感觉表述不清楚,想好了表述方式再修改吧,下面是代码,已通过pongo
#include<iostream>
#include<list>
#include<ctime>
#include<cstdlib>
#include<map>
#include<cstring>
bool isPure(std::list<char>&lch){
char tmp='a';
std::list<char>::const_iterator cit=lch.begin();
if(cit==lch.end())return true;
tmp=*cit;
for(cit++;cit!=lch.end();cit++)
if(*cit!=tmp)return false;
return true;
}//isPure
int minLength(const char *s) {
std::list<char> lch(s,s+strlen(s));
std::map<std::size_t,std::size_t> nums;
size_t first=97,second=98,third=99,tmpNum=0;
bool findC=false;
nums[97]=0;
nums[98]=0;
nums[99]=0;
for(std::list<char>::const_iterator cit=lch.begin();cit!=lch.end();cit++)
nums[(size_t)*cit]++;
int mmm=0;
while(!isPure(lch)){
findC=false;
if(nums[second]>nums[first]){
tmpNum=first;
first=second;
second=tmpNum;
}//if
if(nums[third]>nums[first]){
tmpNum=first;
first=third;
third=second;
second=tmpNum;
}else if(nums[third]>nums[second]){
tmpNum=third;
third=second;
second=tmpNum;
}
for(std::list<char>::const_iterator cit=lch.begin();cit!=lch.end();cit++){
std::list<char>::const_iterator citj=cit;
citj++;
if(citj==lch.end())break;
if(*cit==first&&*citj==second||*cit==second&&*citj==first){
findC=true;
cit=lch.erase(cit,++citj);
lch.insert(cit,third);
nums[first]--;
nums[second]--;
nums[third]++;
break;
}//if
}//for
if(!findC)
for(std::list<char>::const_iterator cit=lch.begin();cit!=lch.end();cit++){
std::list<char>::const_iterator citj=cit;
citj++;
if(citj==lch.end())break;
if(*cit==first&&*citj==third||*cit==third&&*citj==first){
cit=lch.erase(cit,++citj);
lch.insert(cit,second);
nums[first]--;
nums[third]--;
nums[second]++;
break;
}//if
}//for
}//while
return lch.size();
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
const int num=200;
std::list<char> lch;
char * cs=new char[num+1];
srand(static_cast<unsigned int>(time(NULL)));
for(int i=0;i<num;i++){
char tmpc=rand()%3+97;
cs[i]=tmpc;
lch.push_back(tmpc);
}
cs[num]='\0';
/*for(std::list<char>::const_iterator cit=lch.begin();cit!=lch.end();cit++)
std::cout<<*cit<<" ";
std::cout<<std::endl;*/
std::cout<<"num="<<minLength(cs);
return EXIT_SUCCESS;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。