XTU-OJ 1347-消消乐

题目描述

你有若干个彩球排成一列,你可以交换相邻的两个球。 如果出现含被交换球的3个或者以上的的同颜色彩球,那么这些彩球就会消失,右边的彩球会向左边靠拢填满空间。 现在给你一个操作的序列,请依次输出每次操作后的彩球序列。

输入

第一行是一个整数T(1≤T≤100),表示样例的个数。 每个样例包含两行,第一行是一个字符串,长度不超过30,只含大写字母'A'-'C',表示不同字母表示不同颜色的球。第二行开始是一个整数n(1≤n≤10),表示操作的个数,以后n个整数ai表示将ai和ai+1交换。输入数据保证是合法的操作。

输出

每个样例的每行输出一个操作后彩球的状况,每个样例最后输出一个空行。

样例输入

4
AABABBB
1 3
AAAABBBBC
2 4 4
AAAAAA
1 2
AABAABBB
2 3 1 

样例输出

Over

AAABABBBC
C

Over

BABBB
A

解题思路:又是一道烧脑的模拟题,还是老老实实跟着题目走吧。

1. 先输入(注意这里用scanf("%s",balls),是从下标0开始输入的,没有与题目的ai保持一致,因为从下标1开始输入,后续不好处理balls数组)所以之后输入的 ai 要 -1。

2. 找到对应小球交换。

*3. 怎么判断是否要消除小球:就找交换后,连着的小球相同数是否大于等于3,交换后的小球,左边的就向左考虑,右边的向右考虑(这种没有同时向两边考虑的就要多处理一下,11、21行代码,要考虑交换的两个小球是否是一样的)

4. 定义好两个方向的 左右边界(left、right),如果为相同小球就 left1-- 或 right2 ++,如果最后 right-left >= 2,就说明有三个及以上的相同小球,要给它消掉。用一个中间数组,存下消去后剩下的小球,然后用 strcpy() 函数 复制给 balls数组。 最后判断输出。

AC代码:

#include <stdio.h>
#include <string.h>

int T,n,ai,len;
char balls[35];
int left1,right1,left2,right2;

void examleft(char C,int r)
{
    left1 = right1 = r; 
    if (balls[r+1] == C)    right1 = r+1;   // 如果交换的两个小球是一样的,那要从它后面算起
    for ( ; left1 >= 0; left1 --)   
        if (balls[left1] != C)
            break;
    left1 ++;      // 因为for循环是最后执行 left--的,所以left都停留在“下一位”,这里给它回退一位
}

void examright(char C,int l)
{
    left2 = right2 = l;
    if (balls[l-1] == C)    left2 = l-1;    // 从前面一位开始
    for ( ; right2 < len; right2 ++)
        if (balls[right2] != C)
            break;
    right2 --;    // 同上
}

void wipe()
{
    int cnt = 0;
    char newball[35] = {0};
    if (right1-left1 >= 2)      // 相差>=2,说明中间隔了三个及以上的相同小球,可消去
        for (int i = left1; i <= right1; i ++)
            balls[i] = ' ';
    if (right2-left2 >= 2)
        for (int i = left2; i <= right2; i ++)
            balls[i] = ' ';
    
    for (int i = 0; i < len; i ++)
        if (balls[i] != ' ')
            newball[cnt++] = balls[i];
    strcpy(balls,newball);
    if (balls[0] == '\0')   puts("Over");
    else    printf("%s\n",balls);
}

int main()
{
    scanf("%d",&T);
    while ( T --)
    {
        scanf("%s",balls);
        scanf("%d",&n);
        for (int i = 0; i < n; i ++)
        {
            len = strlen(balls);
            scanf("%d",&ai);    ai --;       // 题目默认是从1开始数,我们是从0下标开始输入的,所以-1
            char c = balls[ai];              // 交换
            balls[ai] = balls[ai+1], balls[ai+1] = c;
            examleft(balls[ai],ai);          // 查找是否可消除小球
            examright(balls[ai+1],ai+1);
            wipe();
        }
        puts("");
    }
    return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值