首页 > 试题广场 >

红和绿

[编程题]红和绿
  • 热度指数:1766 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
牛牛有一些排成一行的正方形。每个正方形已经被染成红色或者绿色。牛牛现在可以选择任意一个正方形然后用这两种颜色的任意一种进行染色,这个正方形的颜色将会被覆盖。牛牛的目标是在完成染色之后,每个红色R都比每个绿色G距离最左侧近。牛牛想知道他最少需要涂染几个正方形。
如样例所示: s = RGRGR
我们涂染之后变成RRRGG或RRRRR就满足要求了,涂染的个数都为2,没有涂染个数更少的方案了。

输入描述:
输入包括一个字符串s,字符串s长度length(1 ≤ length ≤ 50),其中只包括'R'或者'G',分别表示红色和绿色。


输出描述:
输出一个整数,表示牛牛最少需要涂染的正方形数量
示例1

输入

RGRGR

输出

2
示例2

输入

GGGGRRR

输出

3

说明

可以将GGGGRRR涂染成GGGGGGG,所以最少需要涂染3个正方形。  
= = 快结束的时候灵光一闪,好zz
直接枚举前面有多少个'R'就完事了= =
O(50*50)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

string s;

int work(string t){
    int ans=0;
    for(int i=0;i<(int)t.size();i++){
        if(s[i]!=t[i])  ans++;
    }
    return ans;
}

int main(void){
    cin >> s;
    int ans=INT_MAX;
    for(int cntR=0;cntR<=(int)s.size();cntR++){
        string t="";
        for(int i=1;i<=cntR;i++) t+='R';
        for(int i=1;i<=(int)s.size()-cntR;i++) t+='G';
        ans=min(ans,work(t));
    }
    cout << ans << endl;

    return 0;
}

发表于 2018-11-21 20:06:54 回复(1)
这个题感觉比后面两个要难想一点,是看了一下网上的解法,自己实现的。大体思路是 设置两个数组分别代表每一位上的左和右需要做多少改变,比如RGRGR中的最中间的R 其实如果左边都是R 右边都是G 那这个位置上是R还是G是无所谓的,那么left[2]和right[2]都是1,也就是等于在第二位(左边从0开始计数)时,左边需要改动1位,右边也需要改动1位,那么这个位置就需要改动1+1=2位,分别算出每一位上左右两边需要改动之和,找和的最小值即可。
下面附上代码 菜鸟写的 不好请见谅。 
#include<iostream>
#include<string>
using namespace std;

int main() {
    string s;
    cin >> s;
    int len = s.size();
    int* left = new int[len];
    int* right = new int[len];
    left[0] = right[len-1] = 0;
    for (int i = 1; i <= len-1; ++i) 
        left[i] = left[i - 1] + (s[i - 1] == 'G' ? 1 : 0);
    for (int i = len - 2; i >= 0; --i)
        right[i] = right[i + 1] + (s[i + 1] == 'R' ? 1 : 0);
    int min=100000000;
    for (int i = 0; i < len; ++i) {
        int sum = left[i] + right[i];
        if (sum < min)
            min = sum;
    }
    cout << min << endl;
    return 0;
}

发表于 2018-10-06 22:05:52 回复(2)
s = input()
# 设定涂染数量的初始值为字符串的长度,即为需要涂染的最大值
num = len(s)
# 题意:把红色全部放在左边,绿色放在右侧。
# 假定左侧有0,1,2,。。。。个红色,通过切片判断需要涂染的次数,然后取最小值
for i in range(len(s)):
    nn = s[:i].count("G") + s[i:].count("R")
    if nn < num:
        num = nn
print(num)

发表于 2023-04-14 18:41:38 回复(0)
我怎么感觉,这题跟动态规划好像没啥关系???
发表于 2023-11-10 18:18:59 回复(0)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    while ((line = await readline())) {
        let RNum = line.split("R").length - 1;
        let GNum = line.split("G").length - 1;
        let NeedNum = Math.min((line.slice(0, RNum).split("G").length - 1) * 2,RNum,GNum);
        console.log(NeedNum);
    }
})();
发表于 2023-08-04 09:52:10 回复(0)
n = input()
list1 = []  # 存索引
for i in range(len(n)):
    if n[i] == "R":
        list1.append(i)
list2 = []
for i in range(len(list1)):
    list2.append((list1[i] - i) + (len(list1) - i - 1))  # 前几个G换成R      #后右边有几个R换成G
# 所有的R换成G
list2.append(len(list1))
# 最后一个R之前所有的G换成R
list2.append(list1[-1] - len(list1) + 1)
print(min(list2))
发表于 2023-04-11 18:45:54 回复(0)
每循环到一个新字符就结合之前算出的数据来计算最新的值并更新它
package main

import (
    "fmt"
    "math"
)

func main() {
    var input string 
    fmt.Scan(&input)

    resultCount, gCount := 0, 0
    for _, s := range []byte(input) {
        if s == 'R' {
            // 往右走碰到R则需要改变,或者改变之前的G,两者取最小的方案
            resultCount = int(math.Min(float64(resultCount+1), float64(gCount)))
        }else {
            // 碰到G,则记录起来
            gCount++
        }
    }
    fmt.Println(resultCount)
}


发表于 2023-02-16 23:34:05 回复(0)
其实这题就是把最后结果变成R...RG..G的样子,那就好说了,假设从左边第一个开始为RG分界点,依次往右遍历,每个位置遍历一次。不过这样复杂度为O(n^2),那就先计算所有RG个数,每碰到一个R就把g2r-1,碰到一个G就r2g+1,这样就不需要每个位置都计算修改个数了,复杂度也就成了O(n)。
int redandgreen_137842(string in)
{
    int r2g=0, g2r=0;
    int r=0, g=0;
    for(int i=0;i<in.size();i++)
    {
        if(in[i]=='R')
            r++;
        else
            g++;
    }
    r2g=r;
    int min=r2g+g2r;
    for(int i=0;i<in.size();i++)
    {
        if(in[i]=='G')
        {
            g2r++;
        }
        if(in[i]=='R')
        {
            r2g--;
        }
        if(g2r+r2g<min)
            min=g2r+r2g;
    }
    return min;
}

发表于 2022-12-29 23:26:32 回复(0)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
  Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        System.out.println(minPaint2(s));
    }
    public static int minPaint2(String s) {
        int n = s.length();
        //预处理数组
        int[] left = new int[n];//记录从0...i  左侧的G的个数
        int[] right = new int[n];//记录 从 i...n-1  右侧的R的个数
        char[] chars = s.toCharArray();
        left[0] = 0;
        for (int i = 1; i < n; i++) {
            left[i] = left[i - 1] + (chars[i - 1] == 'G' ? 1 : 0);
        }
        right[n - 1] = 0;
        for (int i = n - 2; i >= 0; i--) {
            right[i] = right[i + 1] + (chars[i + 1] == 'R' ? 1 : 0);
        }
        int numMin = Integer.MAX_VALUE;
        for (int i = 0; i < n; i++) {
            int min = right[i] + left[i];
            numMin = Math.min(numMin, min);
        }
        return numMin;
    }
}
发表于 2022-05-16 19:20:47 回复(0)
int main() {
    string s;
    cin >> s;
    
    int green = 0, red = 0;
    
    for (char c : s) {
        if (c == 'R') red++;
    }
    
    int count = red;
    
    for (char c : s) {
        if (c == 'R') red--;
        else green++;
        count = min(count, red + green);
    }
    
    cout << count;
    
    return 0;
}

发表于 2022-03-11 20:44:12 回复(0)
枚举
#include <bits/stdc++.h>
using namespace std;
int main() {
    string s;
    cin >> s;
    int n = s.size();
    int ans = INT_MAX;
    for (int i = 0; i <= n; i += 1) {
        int cnt = 0;
        for (int j = 0; j < i; j += 1) {
            if (s[j] == 'G') {
                cnt += 1;
            }
        }
        for (int j = i; j < n; j += 1) {
            if (s[j] == 'R') {
                cnt += 1;
            }
        }
        ans = min(ans, cnt);
    }
    cout << ans;
}


发表于 2022-03-02 20:18:32 回复(0)
参照 小冲冲的思路:
我的代码如下 
其中 R,G的判断根据他们的二进制码
G:
e & 0x1

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);       
        char[] q = in.nextLine().toCharArray();
        int a = 0,b = 0,c = 0,d = 0;c = 50;
        for(char e : q){            
            a += d = e & 0x1;
            b += d ^ 0x1;
            c = Math.min(a-b,c);
        }
        d = Math.min(Math.min(a,b),b+c);
        System.out.println(d);
    }
}

编辑于 2021-04-06 14:47:13 回复(0)
s = input()
r = 0
r_need = 0
for i in s:
    if (i == 'R'):
        r += 1
for i in range(r):
    if (s[i] == 'G'):
        r_need += 1
print(r_need*2)
用例输入:GGGGRRR
用例输出:3    ??????
不应该是染6次吗


发表于 2020-12-03 21:27:13 回复(2)
解析:使用两个数组lsz和rsz,lsz表示str中当前字符左边的‘G’个数,rsz表示str中当前字符右边的‘R’个数.然后从头至尾相加,找出最小和即为答案。代码如下:
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
string str = "";
getline(cin, str);
int size = str.size();
vector<int>ldp(size, 0);
vector<int>rdp(size, 0);
// 填写当前ldp中当前数左边的G的个数
int l=0;
for(int i=0; i<size; ++i)
{
ldp[i] = l;
if(str[i] == 'G')
++l;
}
// 填写当前rdp中当前数右边的R的个数
int r=0;
for(int i=size-1; i>=0; --i)
{
rdp[i] = r;
if(str[i] == 'R')
++r;
}
// 开始计算
int res = 100;
for(int i=0; i<size; ++i)
{
if(ldp[i] + rdp[i] < res)
res = ldp[i] + rdp[i];
}
cout << res << endl;
return 0;
}
编辑于 2018-09-14 20:51:24 回复(1)
#include <iostream>
using namespace std;
int main() {
    string s;
    int r[55],g[55];
    while(cin>>s){
        r[0]=g[0]=0;
        for(int i=0;i<s.size();i++){
            if(s[i]=='R'){
                r[i+1]=r[i]+1;
                g[i+1]=g[i];
            }else{
                r[i+1]=r[i];
                g[i+1]=g[i]+1;
            }
        }
        ///统计R和G的数量
        int sumR=r[s.size()];
        int sumG=g[s.size()];
        ///最坏情况,就是把R全变为G或者把G全部变为R
        int res=min(sumR,sumG);
        for(int i=1;i<=s.size();i++){
            ///遍历每个点需要修改的数量,记录最小值即可
            res=min(res,g[i]+sumR-r[i]);
        }
        cout<<res<<endl;
    }
    return 0;
}

发表于 2018-08-24 11:06:38 回复(0)
/*
思路:
分为奇偶两个情况
分头尾两个,同时向中间靠拢,
在此期间计算左边要修改的G的数,
右边要修改R的数,两者相加返回p+q的值
*/

#include <iostream>
#include <array>
#include <string>
#define R_G_SIZE 100
using namespace std;
int main(int argc, char *argv[]) {
    string r_g_str;
    char r_g_ary[R_G_SIZE];
    int q = 0;
    int p = 0;            //这两个数用来计算head从左到右修改次数,p用来计算rear从右到左修改次数
    cout << "please input a string about 'R' & 'G' representative red and green:  " << endl;
    cin >> r_g_str;
    strcpy_s(r_g_ary, r_g_str.c_str());
    for (int i = 0; i < strlen(r_g_ary); i++) {
        cout << r_g_ary[i] << endl;
    }
    int *rear;
    int *head;
    if (strlen(r_g_ary) % 2 != 0) {                //个数为奇数
        for (int j = 0; j < (strlen(r_g_ary)-1)/2; j++)
        {
            if (r_g_ary[j] == 'G')
            {
                p++;
            }
            else{}
            if (r_g_ary[strlen(r_g_ary)-1-j] == 'R')
            {
                q++;
            }
            else {}    
        }
        cout << (p + q);
    }
    else {                                       //个数为偶数
        for (int k = 0; k < (strlen(r_g_ary) / 2); k++) {
            if (r_g_ary[k] == 'G') {
                p++;
            }
            else {}
            if (r_g_ary[strlen(r_g_ary) - 1 - k] == 'R') {
                q++;
            }
            else {}
        }
        cout << (p + q) << endl;
    }
    system("pause");
    return (p + q);
}

发表于 2018-08-09 00:46:17 回复(0)
#include<stdio.h>
#include<string.h>
intmain()
{
    intr = 0, i = 0, n, min = 50, r2 = 0, g2 = 0, x;
    chars[51], *p;
    gets(s);
    for(i = 0; 'R'== s[i]; i++);//去掉头部的R
    p = s + i;
    n = strlen(p);
    for(i = n - 1; i >= 0 && 'G'== p[i]; i--);//去掉尾部的G
    n = i + 1;
    //统计r的数量,其实应该放到下面的else里面
    for(i = 0; i < n; i++)
    {
        if('R'== p[i])
        {
            r++;
        }
    }
    if(0 == n)
    {
        min = 0;
    }
    else
    {
        for(i = 0; i < n; i++)
        {
            //统计0 ~ i 的r和g的数量
            if('R'== p[i])
            {
                r2++;
            }
            else
            {
                g2++;
            }
            x = g2 + r - r2;//以i为界限,左涂g右涂r的数量
            min > x && (min = x);
        }
    }
    //考虑全涂成一色的情况
    if(r < min)
    {
        min = r;
    }
    if(n - r < min)
    {
        min = n - r;
    }
    printf("%d", min);
    return0;
}

发表于 2017-12-07 16:27:57 回复(1)