FJNU.1964
Description
如上图所示,在QQ龙珠游戏中,通过龙头射出珠子,将轨道中的珠子形成同色三个或以上(含射出的珠子)相连的状态而消去这些同色的珠子。如果没有消去珠子,则在相应的位置插入射出的珠子。注意珠子的消去动作是由同色珠子的碰撞诱发的,中间的珠子被消去后两边的珠子向中间靠拢也会产生碰撞。若没有碰撞动作,就算三个或以上的珠子同色相连也不会有消去产生。
示例:
珠子序列为:
AABBAA
对中间的BB射出B,形成:
AABBBAA
符合消去条件消去BBB:
AA***AA
此时两旁的AA向中间靠拢形成:
AAAA
符合消去条件,第二次消去发生,珠子全部被消去。
现由龙头射出一个给定颜色的珠子,如何消去最多的珠子?
Input
第一行为一个正整数n (0<n<100),表示下面有n个测试用例。每个测试用例由两行组成,其中第一行为一个由大写字母组成的长度小于255的字符串,表示珠子序列,另一行只含一个大写字符,表示要发射的珠子。(一个字母代表一个珠子,字母相同则珠子颜色相同)
Output
对应每个测试用例输出一行,含一个正整数,表示最多消去的珠子数目(计数时含射出的珠子)。
Sample Input
1
CABBAAC
B
Sample Output
6
Source
福建师范大学第五届程序设计竞赛
My Program
#include < string .h >
#define M 255
using namespace std;
char dn[M],ch;
int carsh( int left, int right, int n)
... {
int num=right-left; //先将这第一回消去的数目加入总数
int i,j,k,m,f;
for(i=left;i>=0;i--) //从左开始向前找
...{
f=0;
for(j=right;j<n;j++) //从右开始向后找
if(dn[i]==dn[j]&&((dn[i]==dn[j+1])||(dn[i-1]==dn[j]))) //当超过3个相同颜色时计算
...{
k=1;m=1;
while(dn[i]==dn[j+k]) //左边颜色相同个数
k++;
while(dn[i-m]==dn[j]) //右边颜色相同个数
m++;
num+=m+k; //将此次消去的个数加入总数
right=j=j+k; //到此次消去的后一位(继续向后找)
left=i=i-m+1; //到此次消去的前一位(继续向前找)
break;
}
else //如果左右不匹配 则说明没有碰撞 即结束
...{
f=1;
break;
}
if(f==1)
break;
}
return num;
}
int push()
... {
int max=0,now;
int i=0,j,n=strlen(dn);
while(i<n) //寻找第一次碰撞点
...{
if(dn[i]==ch)
...{
j=1;
while(dn[i]==dn[i+j]) //寻找连续的同色珠子个数
j++;
if(j>=2)
now=carsh(i-1,i+j,n); //超过2个颜色相同则满足碰撞,计算可消去数量
i+=j; //连着相同的珠子都忽略,准备寻找下一个满足碰撞条件的珠子
if(now>max)
max=now;
}
else
i++;
}
return max;
}
int main()
... {
int n,s,i;
char temp[4];
scanf("%d",&n);
gets(temp);
for(i=0;i<n;i++)
...{
gets(dn);
scanf("%c",&ch);
gets(temp);
s=push();
printf("%d ",s);
}
return 0;
}
YOYO's Note:
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄它是华丽的分隔线
【题意简述】
龙珠游戏的玩法是,从龙头射出一个珠子,在它碰撞的那个位置形成三个或三个以上相同颜色的珠子时会将珠子消除,同时收缩两边的,如果两边碰撞恰好也形成三个或三个以上相同颜色的珠子时也会被消除。现在N个测试数据,每个各有一个珠子轨道以及一个珠子。相同字母表示相同颜色,求最多可以消除多少个珠子。
【粗略分析】
模拟题。先寻找与珠子相同的连续两个的珠子,找到后指针同时向左右走寻找是否满足碰撞,循环直到不能发生碰撞为止,统计碰撞的个数,继续寻找下一个第一次碰撞的可能发生点。最后找出其中的最大值即可。
【程式优化】
发生碰撞时,假设与发射珠子相同的珠子数目为n,则统计好数目后可直接移动到下n个。
【C++源代码】
#include < string .h >
#define M 255
using namespace std;
char dn[M],ch;
int carsh( int left, int right, int n)
... {
int num=right-left; //先将这第一回消去的数目加入总数
int i,j,k,m,f;
for(i=left;i>=0;i--) //从左开始向前找
...{
f=0;
for(j=right;j<n;j++) //从右开始向后找
if(dn[i]==dn[j]&&((dn[i]==dn[j+1])||(dn[i-1]==dn[j]))) //当超过3个相同颜色时计算
...{
k=1;m=1;
while(dn[i]==dn[j+k]) //左边颜色相同个数
k++;
while(dn[i-m]==dn[j]) //右边颜色相同个数
m++;
num+=m+k; //将此次消去的个数加入总数
right=j=j+k; //到此次消去的后一位(继续向后找)
left=i=i-m+1; //到此次消去的前一位(继续向前找)
break;
}
else //如果左右不匹配 则说明没有碰撞 即结束
...{
f=1;
break;
}
if(f==1)
break;
}
return num;
}
int push()
... {
int max=0,now;
int i=0,j,n=strlen(dn);
while(i<n) //寻找第一次碰撞点
...{
if(dn[i]==ch)
...{
j=1;
while(dn[i]==dn[i+j]) //寻找连续的同色珠子个数
j++;
if(j>=2)
now=carsh(i-1,i+j,n); //超过2个颜色相同则满足碰撞,计算可消去数量
i+=j; //连着相同的珠子都忽略,准备寻找下一个满足碰撞条件的珠子
if(now>max)
max=now;
}
else
i++;
}
return max;
}
int main()
... {
int n,s,i;
char temp[4];
scanf("%d",&n);
gets(temp);
for(i=0;i<n;i++)
...{
gets(dn);
scanf("%c",&ch);
gets(temp);
s=push();
printf("%d ",s);
}
return 0;
}
【注意事项】
※ 输入的格式:我原来的代码虽然在windows下可以得出正确结果,但在linux系统下一直WA。现在这个是伟大的honghu学长帮忙改的。至今不知道为什么。 = = ……
※ 消除时,珠子本身也算一个被消除的。
※ 不发生碰撞的话,即使有三个以上相同颜色的珠子也不会消除。
【点评】
输入……又是9个WA……