网易调整队形(动态规划)

问题描述
在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n-1)。其中有一些是男生,有一些是女生,
男生用'B'表示,女生用'G'表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,
你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,
现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:
GGBBG -> GGBGB -> GGGBB
这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次

输入描述:
输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.

输出描述:
输出一个整数,表示最少需要的调整队伍的次数

输入例子1:
GGBBG

输出例子1:
2 
动态规划递归式
既然决定使用动态规划求解,那么最重要的就是建立递归式了:
  m[i]为前i个人调整为男女一处相邻的调整队伍次数;
  显而易见, m[1]=0;m[2]=0;
  设前i个人中最后一个人性别为pre,下一个将要加入的人性别为now,均为char类型。

这里写图片描述

动态规划递归式的分析
看完这个递归式,你肯定会有疑问:
1.为什么下面两种情况表达式不同?
2.m[i]+i-index什么鬼?
别急,下面就来一一分析这三种情况:
(1)now==pre  -->  m[i+1]=m[i]
    假设当前串为:GGBBB,待加入的为B:
    加入后:GGBBBB
    那么,直接加入就好,不需要调整。
(2)now!=pre  -->  m[i+1]=m[i]
    当前串为GGGGG,待加入的为B:
    加入后:GGGGGB
    这种情况下,尽管 now!=pre ,也不需要调整。
(3)now!=pre  -->  m[i+1]=m[i]+i-index
    当前串为BBGGG,待加入为B:
    加入后:BBBGGG
    这种情况下:i=5,
             index=2(index代表G出现的第一个位置);
    及:m[i+1]为前i个的调整次数(m[i])加上下一个加入的调整次数(i-index)。
需要记录的信息
(1)pre:前i个人中最后一个人性别
(2)index:前i个中如果存在两种性别,排在后面的性别的第一次出现位置
(3)now:下一个将要加入的人性别
需要说明的
由于默认第一个性别为排序在前面的性别,所以无形中我们漏掉了一种情况,及另一种性别为排序在前面的性别。(代码中会有体现)
代码
import java.util.*;
public class Main{
    public static int getMax(String str){
        int len=str.length();
        if(len<3)   return 0;
        int[] m=new int[len+1];
        m[1]=0;
        m[2]=0;
        char pre=str.charAt(1);
        int index=(str.charAt(0)==str.charAt(1))?-1:1;
        for(int i=2;i<len;i++){
            char now=str.charAt(i);
            if(now==pre)
                m[i+1]=m[i];
            else{
                if(index==-1){
                    index=i;
                    m[i+1]=m[i];
                    pre=now;
                }else{
                    m[i+1]=m[i]+i-index;
                    index++;
                }
            }
        }
        return m[len];
    }
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        String str=scan.next();
        int i;
        for(i=1;i<str.length();i++)
            if(str.charAt(i)!=str.charAt(0))
                break;
        int b=Integer.MAX_VALUE;
        //i==str.length()为所有性别都一样的极端情况
        if(i!=str.length()){
            String ss=""+str.charAt(i)+str.substring(0,i)+
                        str.substring(i+1,str.length());
            b=getMax(ss)+i;
        }    
        int a=getMax(str);
        System.out.println(Math.min(a,b));
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值