UESTC 490 Swap Game (特殊的求解逆序对数)

3 篇文章 0 订阅
2 篇文章 0 订阅

Swap Game

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

Last week, children of the kindergarten which Lily attends organized a dinner party to welcome children from their neighborhood kindergarten. Lots of candy and fruit were offered and children all had a good time. What’s more, they played a special game designed by Miss Xue. In this game, children of each kindergarten wore clothes with specific color. The color assigned to clothes for Lily’s kindergarten is red, and for the neighborhood kindergarten is blue.

Children stood in a circle. Adjacent children could swap their place with each other. Miss Xue asked the children to swap so that in the end children of the same kindergarten formed a consecutive sequence.

title

This game is so funny that everyone was happy. However, Lily wants to know what the minimum number of swaps is needed for children to accomplish the game, given the initial state of the circle. Can you tell her?

Input

First an integer T

( T20

), indicates the number of test cases.

Every test case contains a string which represents the color of clothes children wore at each place. Specifically, ith

element of the string is R if the child stood at ith place is from Lily’s kindergarten, B otherwise. Note that the first child is adjacent with the last one. The length of the string is not greater than 100000

.

Output

For every test case, you should output Case #k: first, where k

indicates the case number and counts from 1

. Then output the minimum number of swaps needed.

Sample input and output

Sample InputSample Output
2
RBRBR
BBRBBRBBBRRR
Case #1: 1
Case #2: 5

Source

Sichuan State Programming Contest 2011

大体题意:
给你一个字符串,其中R表示红球,B 表示蓝球,其中字符串首尾相连。你可以交换任意相邻的球,问最少交换几次,使得红球在一边,蓝球在一边。
思路:
这个题目比赛没做出来,后来看的学长的博客补得题目。
  把RB想成1和0,换一个类似的简单题目来想,如果RB表示的字符串不是一个环,而是一条链的话,那么这个题目就是求逆序对数了,因为交换一次,最多交换一个逆序对,如果你的做法是最优的话,那么每一次交换都可以换一个逆序对,因此如果是一条链的话,那就是逆序对数量。
  这个题目需要变通一下,因为是一个环嘛,所以可以把左边的R变成1,B变成0,右边的R变成0,B变成1,这样两边分别求逆序对数,在相加,这就是其中一个答案,最优解答案,就是枚举所有的左右情况,求出最小的答案!
具体看代码 分析!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000 + 10;
char s[maxn];
int main(){
    int T,cnt = 0;
    scanf("%d",&T);
    while(T--){
        scanf("%s",s);
        int len = strlen(s);
        int posmid = len >> 1;//求出中间位置!
        int inver = 0;//表示从中间分为左右两侧的逆序对答案数!
        int tmp[2] = {}; // tmp[0]记录左边R(也就是1)的个数,tmp[1]记录右边B(也就是1)的个数。
        for (int i = 0; i < posmid; ++i){
            if (s[i] == 'R') ++tmp[0];
            else inver += tmp[0];
        }
        for (int i = posmid; i < len; ++i){
            if (s[i] == 'B')++tmp[1];
            else inver += tmp[1];
        }//以上两个循环,可以求得 从中间一分为二的逆序对数,和 左边1的个数和右边1的个数!
        int ans = inver;
        for (int i = 0; i < len; ++i){
            int t = (posmid + i) % len;  //  这样可以用s[t]表示右边的需要加入左边的字符,s[i]表示左边的需要加入右边的字符!
            if (s[t] == 'B'){
                inver += tmp[0] - (s[i] == 'R');
                inver -= (len-posmid-tmp[1]);
            }
            if (s[i] == 'R'){
                inver += tmp[1] - (s[t] == 'B');
                inver -= posmid-tmp[0];
            }// 以上两个判断  画一个样例图分析一下即可!
            if (s[i] == 'R')--tmp[0];
            else ++tmp[1];
            if (s[t] == 'B')--tmp[1];
            else ++tmp[0];// 移动完后 更新左右1的个数!
            ans = min(ans,inver);
        }
        printf("Case #%d: %d\n",++cnt,ans);

    }

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值