首页 > 试题广场 >

画家小Q

[编程题]画家小Q
  • 热度指数:5276 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
画家小Q又开始他的艺术创作。小Q拿出了一块有NxM像素格的画板, 画板初始状态是空白的,用'X'表示。
小Q有他独特的绘画技巧,每次小Q会选择一条斜线, 如果斜线的方向形如'/',即斜率为1,小Q会选择这条斜线中的一段格子,都涂画为蓝色,用'B'表示;如果对角线的方向形如'\',即斜率为-1,小Q会选择这条斜线中的一段格子,都涂画为黄色,用'Y'表示。
如果一个格子既被蓝色涂画过又被黄色涂画过,那么这个格子就会变成绿色,用'G'表示。
小Q已经有想画出的作品的样子, 请你帮他计算一下他最少需要多少次操作完成这幅画。

输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数N和M(1 <= N, M <= 50), 表示画板的长宽。
接下来的N行包含N个长度为M的字符串, 其中包含字符'B','Y','G','X',分别表示蓝色,黄色,绿色,空白。整个表示小Q要完成的作品。


输出描述:
输出一个正整数, 表示小Q最少需要多少次操作完成绘画。
示例1

输入

4 4
YXXB
XYGX
XBYY
BXXY

输出

3

说明

XXXX
XXXX
XXXX
XXXX
->
YXXX
XYXX
XXYX
XXXY
->
YXXB
XYBX
XBYX
BXXY
->
YXXB
XYGX
XBYY
BXXY

每画一步追求最大连笔,同时将已经画了某种颜色的格子元素设置为下一步需要画的颜色,如原Y画了Y下一步不需要再画设置为X.

package com.plf.tencent;

import java.util.Scanner;

public class XiaoQDrawer {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        String tem = scanner.nextLine();
        int n = Integer.valueOf(tem.split(" ")[0]);
        int m = Integer.valueOf(tem.split(" ")[1]);
        char color[][] = new char[n][m];
        for (int i = 0; i < n; i++) {
            tem = scanner.nextLine();
            for (int j = 0; j < tem.length(); j++) {
                color[i][j] = tem.charAt(j);
            }
        }

        // 获取最小步数
        getMinStep(n, m, color);

        scanner.close();

    }

    /**
     * 获取最小步数 每画一个线直到颜色不同为止
     * 
     * @param n
     * @param m
     * @param color
     */
    private static void getMinStep(int n, int m, char color[][]) {

        int step = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (color[i][j] == 'Y') {
                    dfs_y(i, j, n, m, color); // 画y
                    step++;
                } else if (color[i][j] == 'B') {
                    dfs_b(i, j, n, m, color); // 画B
                    step++;
                } else if (color[i][j] == 'G') {
                    dfs_y(i, j, n, m, color); // 先画y
                    step++;
                    dfs_b(i, j, n, m, color); // 在画B
                    step++;
                }
            }
        }

        System.out.println(step);
    }

    /**
     * 当前位置画y,是否在后续位置继续画y
     * 
     * @param x
     * @param y
     */
    private static void dfs_y(int x, int y, int n, int m, char color[][]) {
        // 根据要求决定当前位置是否能画y
        if (x >= 0 && x < n && y >= 0 && y < m && (color[x][y] == 'Y' || color[x][y] == 'G')) {
            if (color[x][y] == 'G') {
                color[x][y] = 'B'; // 如果当前位置要求画的是G,那么画了Y之后下一次只能画B
            } else {
                color[x][y] = 'X'; // 如果当前位置要求画的是Y,那么画了Y之后下一次不需要再画
            }

            // 是否连笔继续画,Y对应的是画\,即左上或者右下
            dfs_y(x - 1, y - 1, n, m, color);
            dfs_y(x + 1, y + 1, n, m, color);

        }

    }

    /**
     * 当前位置画B,是否在后续位置继续画B
     * 
     * @param x
     * @param y
     */
    private static void dfs_b(int x, int y, int n, int m, char color[][]) {
        // 根据要求决定当前位置是否能画B
        if (x >= 0 && x < n && y >= 0 && y < m && (color[x][y] == 'B' || color[x][y] == 'G')) {
            if (color[x][y] == 'G') {
                color[x][y] = 'Y'; // 如果当前位置要求画的是G,那么画了Y之后下一次只能画Y
            } else {
                color[x][y] = 'X'; // 如果当前位置要求画的是B,那么画了B之后下一次不需要再画
            }

            // 是否连笔继续画,B对应的是画/,即左下或者右上
            dfs_b(x + 1, y - 1, n, m, color);
            dfs_b(x - 1, y + 1, n, m, color);

        }
    }

}
编辑于 2018-08-02 18:47:52 回复(2)

思路还是比较明确的,一遍AC了。
最求的是一笔尽可能给多个格子上色,然后主要分两种上色方案,如代码所示,有另一个矩阵记录当前位置,是否在之前已经被访问过。

n,m = map(int, input().split())
graph = []
for i in range(n):
    color = input()
    graph.append(color)
visited = [[0] * m for _ in range(n)]
def colorY(i,j,visited,graph):
    while i < n and j < m:
        if graph[i][j] == 'G' or graph[i][j] == 'Y':
            visited[i][j] += 1
            i += 1
            j += 1
        else:
            break
def colorB(i,j,visited,graph):
    while i < n and j >= 0:
        if graph[i][j] == 'G' or graph[i][j] == 'B':
            visited[i][j] += 2
            i += 1
            j -= 1
        else:
            break
res = 0
for i in range(n):
    for j in range(m):
        if graph[i][j] == 'Y' and visited[i][j] == 0:
            colorY(i,j,visited,graph)
            res += 1
        if graph[i][j] == 'B' and visited[i][j] == 0:
            colorB(i,j,visited,graph)
            res += 1
        if graph[i][j] == 'G' and visited[i][j] == 0:
            colorY(i, j, visited, graph)
            colorB(i, j, visited, graph)
            res += 2
        if graph[i][j] == 'G' and visited[i][j] == 1:
            colorB(i, j, visited, graph)
            res += 1
        if graph[i][j] == 'G' and visited[i][j] == 2:
            colorY(i, j, visited, graph)
            res += 1
print(res)
发表于 2019-08-10 16:40:31 回复(3)
踩过的坑:首先读懂题意,其中 '/'必须涂蓝色 '\'必须涂黄色
基本思想:将所给二维数组还原成原来空白情况,即全部为'X',为此只需遍历(并修改数组的所有字符。对于每一个字符,如果是'B'就向左下扫描,遇到'B'或者'G'则继续(在左下扫描过程中,将所有的B替换为X,G替换成Y),否则立即停止;如果字符是'Y',就向右下扫描,遇到Y或者G继续(将所有的Y替换成X,G替换成B),否则停止扫描;如果字符是G,则先将其替换成B,按'B'处理方式扫描,再将其替换成Y,按Y的处理方式扫描。每执行一次左下或者右下扫描,操作次数+1。

C++代码如下:
#include <iostream>
#include <vector>
using namespace std;

void refix(vector<vector<char>>& arr,int& n,int& m,int x,int y,int& ans){//B Y
    char ch = arr[x][y];
    arr[x][y]='X';
    int i,j;

    if(ch=='B'){//左下画线
        i=x+1;j=y-1;
        while(i<n && j>-1){
            if(arr[i][j]==ch) arr[i][j]='X';
            else if(arr[i][j]=='G') arr[i][j]='Y';
            else break;
            ++i,--j;
        }
    }
    else{//右下画线
        i=x+1;j=y+1;
        while(i<n && j<m){
            if(arr[i][j]==ch) arr[i][j]='X';
            else if(arr[i][j]=='G') arr[i][j]='B';
            else break;
            ++i,++j;
        }
    }
    
    ans+=1;
}

int main(){
    int N,M;
    cin >> N >> M;
    vector<vector<char>> arr(N,vector<char>(M));
    for(int i=0;i<N;++i){
        for(int j=0;j<M;++j)
            cin >> arr[i][j];
    }
    int ans = 0;
    for(int i=0;i<N;++i){
        for(int j=0;j<M;++j){
            if(arr[i][j]=='X') continue;
            else if(arr[i][j]=='B') refix(arr,N,M,i,j,ans);
            else if(arr[i][j]=='Y') refix(arr,N,M,i,j,ans);
            else {//当前为'G'
                arr[i][j]='B';refix(arr,N,M,i,j,ans);
                arr[i][j]='Y';refix(arr,N,M,i,j,ans);
            }
        }
    }
    cout << ans;
    return 0;
    
}


编辑于 2020-03-18 21:46:27 回复(0)
import java.util.*;
public class Main{
public static void main(String[]args){
Scanner scanner = new Scanner(System.in);
String tem = scanner.nextLine();
// 读入n的值
int n = Integer.valueOf(tem.split(" ")[0]);
// 读入m的值
int m = Integer.valueOf(tem.split(" ")[1]);
//存放颜色的字符型数组
char color[][] = new char[n][m];
for (int i = 0; i < n; i++) {
tem = scanner.nextLine();
//按行读入颜色到字符型数组
for (int j = 0; j < tem.length();j++) {
color[i][j] = tem.charAt(j);
}
}
//求数组的行的最大下标
n=n-1;
//求数组的列的最大下标
m=m-1;
//调用求最小步数的方法
System.out.print(getMinStep(color,n,m));
}
//求最小步数的方法
public static int getMinStep(char [][]color,int n,int m){
//统计步数
int step=0;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
//如果值为绿色G 或者黄色Y 说明画的是“\” 是黄色,把黄色清除掉,并将步数加一
if(color[i][j]=='G'||color[i][j]=='Y'){
//调用清除黄色的方法 因为画的是“\”,所以要将 i+1,j+1
clearY(color,i+1,j+1,n,m);
//步数加一
step++;
}
//如果值为绿色G 或者蓝*** 说明画的是“/” 是B蓝色,把蓝色清除掉,并将步数加一
if(color[i][j]=='B'||color[i][j]=='G'){
//调用清除蓝色的方法,因为画的是“/”,所以要将 i-1,j+1
clearB(color,i+1,j-1,n,m);
//步数加一
step++;
}
continue;
}
}
return step;
}
//清除黄色Y的方法
public static void clearY(char [][]color,int i,int j,int n,int m){
//判断边界条件
while(n>=i&&m>=j){
//如果是绿色G,恢复到B蓝***r /> if(color[i][j]=='G'){
color[i][j]='B';
}
//如果是黄色Y,恢复到白色X
else if(color[i][j]=='Y'){
color[i][j]='X';
}
//如果是白色X,说明该斜线“\”断开了,后面的值不能修改,因为那是第二次画斜线的
//举例
/**
YXXX
XYXX
XXXX
XXXY
这算画了两次*/
else{
break;
}
i++;
j++;
}
}
//清除B蓝色的方法
public static void clearB(char [][]color,int i,int j,int n,int m){
//判断边界条件
while(n>=i&&j>=0){
//如果是绿色G,恢复到黄色Y
if(color[i][j]=='G'){
color[i][j]='Y';
}
//如果是蓝色G,恢复到白色X
else if(color[i][j]=='B'){
color[i][j]='X';
}
//如果是白色X,说明该斜线“/”断开了,后面的值不能修改,因为那是第二次画斜线的
//举例
/**
XXXB
XXXX
XBXX
BXXX
这算画了两次*/
else{
break;
}
i++;
j--;
}
}
}

编辑于 2019-09-05 22:58:47 回复(0)
import sys
class min_step():
    def __init__(self,matrix,M,N):
        self.matrix=matrix
        self.M=M
        self.N=N
        self.count=0
        
    def colour_Y(self,m,n):
        self.count=self.count+1
        while m<self.M and n<self.N:
            if self.matrix[m][n]=='Y':
                self.matrix[m][n]='X'
            elif self.matrix[m][n]=='G':
                self.matrix[m][n]='B'
            else:
                break
            m=m+1
            n=n+1
    def colour_B(self,m,n):
        self.count=self.count+1
        while m<self.M and n>=0:
            if self.matrix[m][n]=='B':
                self.matrix[m][n]='X'
            elif self.matrix[m][n]=='G':
                self.matrix[m][n]='Y'
            else:
                break
            m=m+1
            n=n-1
    def colour_G(self,m,n):
        self.count=self.count+1
        while m<self.M and n>=0:
            if self.matrix[m][n]=='B':
                self.matrix[m][n]='X'
            elif self.matrix[m][n]=='G':
                self.matrix[m][n]='Y'
            else:
                break
            m=m+1
            n=n-1
    def get_min_step(self):
        for i in range(0,self.M):
            for j in range(0,self.N):
                if self.matrix[i][j]=='Y':
                    self.colour_Y(i, j)
                elif self.matrix[i][j]=='B':
                    self.colour_B(i, j)
                elif self.matrix[i][j]=='G':
                    self.colour_G(i,j)
                    self.colour_Y(i,j)
        return self.count
m,n=map(int,sys.stdin.readline().strip().split(' '))
painting_matrix=[]
for i in range(0,m):
    temp_line=list(sys.stdin.readline().strip())
    painting_matrix.append(temp_line)

Q_min_step=min_step(painting_matrix,m,n)
print (Q_min_step.get_min_step())
发表于 2018-08-03 20:30:04 回复(0)
#思路,先读入数据,用一个矩阵存1、2、3代表三种颜色,3同时表示1、2,并且保存1、2的位置信息
#利用堆栈,遍历所有规定方向上的1、2,把每一个连通域记下,最后输出连通域数量即可

n, m = input().split()
n, m = int(n), int(m)
 matrix = [[None for i in range(m)] for j in range(n)]
 dic = {"0":[],"1":[],"2":[]}
 for i in range(n):
 line = input()
 for j in range(len(line)):
 if line[j] == "X":
 matrix[i][j] = 0
 dic["0"].append([i,j])
 elif line[j] == "B":
 matrix[i][j] = 1
 dic["1"].append([i,j])
 elif line[j] == "Y":
 matrix[i][j] = 2
 dic["2"].append([i,j])
 else:
 matrix[i][j] = 3
 dic["1"].append([i,j])
 dic["2"].append([i,j])
 def in_list(li, a):
 #print(li, a)
 for i in range(len(li)):
 if li[i] == a:
 return i
 return None
 draw = []
 while len(dic["1"]):
 stack = []
 temp = []
 t0 = dic["1"].pop(0)
 stack.append(t0)
 while len(stack):
 t = stack.pop(0)
 temp.append(t)
 if t[0] - 1>=0 and t[1] + 1 < m and (matrix[t[0] - 1][t[1] + 1] == 1 or matrix[t[0] - 1][t[1] + 1] == 3):
 ind = in_list(dic["1"], [t[0] - 1, t[1] + 1])
 if ind != None:
 stack.append(dic["1"][ind])
 dic["1"].pop(ind)
 if t[0] + 1 < m and t[1]- 1>=0 and (matrix[t[0] + 1][t[1]- 1] == 1 or matrix[t[0] + 1][t[1] - 1] == 3):
 ind = in_list(dic["1"], [t[0] + 1, t[1] - 1])
 if ind != None:
 stack.append(dic["1"][ind])
 dic["1"].pop(ind)
 draw.append(temp)
 while len(dic["2"]):
 stack = []
 temp = []
 t0 = dic["2"].pop(0)
 stack.append(t0)
 while len(stack):
 t = stack.pop(0)
 temp.append(t)
 if t[0] - 1 >= 0 and t[1] - 1>=0 and (matrix[t[0] - 1][t[1] - 1] == 2 or matrix[t[0] - 1][t[1] - 1] == 3):
 ind = in_list(dic["2"], [t[0] - 1, t[1] - 1])
 if ind != None:
 stack.append(dic["2"][ind])
 dic["2"].pop(ind)
 if t[0] + 1 < m and t[1] + 1 < m and (matrix[t[0] + 1][t[1]+ 1] == 2 or matrix[t[0] + 1][t[1] + 1] == 3):
 ind = in_list(dic["2"], [t[0] + 1, t[1] + 1])
 if ind != None:
 stack.append(dic["2"][ind])
 dic["2"].pop(ind)
 draw.append(temp)
 #print(draw)
print(len(draw))

编辑于 2019-04-07 00:36:28 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        //int N=sc.nextInt();
        //int M=sc.nextInt();
        String TempStr=sc.nextLine();
        int N=Integer.valueOf(TempStr.split(" ")[0]);
        int M=Integer.valueOf(TempStr.split(" ")[1]);
        char[][] Color=new char[N][M];
        int[][] HaveDraw=new int[N][M];
        for(int k1=0;k1<N;k1++){
            TempStr=sc.nextLine();
            for(int k2=0;k2<M;k2++){
                Color[k1][k2]=(TempStr.charAt(k2));
            }
        }
        //int N=4;
        //int M=4;
        //int[][] HaveDraw=new int[N][M];
        //char[][] Color=new char[N][M];
        //char[][] Color= {
        		//{'Y','X','X','B'},
        		//{'X','Y','G','X'},
        		//{'X','B','Y','Y'},
        		//{'B','X','X','Y'}
        		//};
		
        int count=0;
        for(int k1=0;k1<N;k1++){
            for(int k2=0;k2<M;k2++){
                if(Color[k1][k2]=='Y'&&HaveDraw[k1][k2]==0){
                    HaveDraw[k1][k2]+=1;
                    int i=k1,j=k2;
                    while(i<N-1&&j<M-1){
                        i++;
                        j++;
                        if(Color[i][j]=='Y'|Color[i][j]=='G'){
                            HaveDraw[i][j]+=1;
                        }
                        else{
                            break;
                        }
                    }
                    count++;
                }
                
                else if(Color[k1][k2]=='B'&&HaveDraw[k1][k2]==0){
                    HaveDraw[k1][k2]+=2;
                    int i=k1,j=k2;
                    while(i<N-1&&j>0){
                        i++;
                        j--;
                        if(Color[i][j]=='B'|Color[i][j]=='G'){
                            HaveDraw[i][j]+=2;
                        }
                        else{
                            break;
                        }
                    }
                    count++;
                }
                
                else if(Color[k1][k2]=='G'){
                    if(HaveDraw[k1][k2]==0){
                        HaveDraw[k1][k2]=HaveDraw[k1][k2]+3;
                        int i=k1,j=k2;
                        int k=k1,h=k2;
                        while(i<N-1&&j<M-1){
                            i++;
                            j++;
                            if(Color[i][j]=='Y'|Color[i][j]=='G'){
                                HaveDraw[i][j]+=1;
                            }
                            else{
                                break;
                            }
                        }
                        while(k<N-1&&h>0){
                            k++;
                            h--;
                            if(Color[k][h]=='B'|Color[k][h]=='G'){
                                HaveDraw[k][h]+=2;
                            }
                            else{
                                break;
                            }
                        }
                        count=count+2;
                    }
                    else if(HaveDraw[k1][k2]==1){
                        HaveDraw[k1][k2]+=2;
                        int i=k1,j=k2;
                        while(i<N-1&&j>0) {
                        	i++;
                        	j--;
                        	if(Color[i][j]=='B'|Color[i][j]=='G') {
                        		HaveDraw[i][j]+=2;
                        	}
                        	else {
                        		break;
                        	}
                        }
                        count++;
                    }
                    else if(HaveDraw[k1][k2]==2) {
                    	HaveDraw[k1][k2]+=1;
                        int i=k1,j=k2;
                        while(i<N-1&&j<M-1) {
                        	i++;
                        	j++;
                        	if(Color[i][j]=='Y'|Color[i][j]=='G') {
                        		HaveDraw[i][j]+=1;
                        	}
                        	else {
                        		break;
                        	}
                        }
                        count++;
                    }
                }
            }
        }
        System.out.println(count);
    }
}
感觉自己写的挺好理解😁
发表于 2020-08-27 11:46:05 回复(0)
将画板反向涂成X。
#include<iostream>
#include<vector>
using namespace std;
void removecolor(vector<vector<char>> &b,int p, int q, char mode){
    int N=b.size();
    int M=b[0].size();
    if(mode=='B'){
        for(int i=p,j=q;i>=0&&j<M;i--,j++){
            if(b[i][j]=='B'){
                b[i][j]='X';
            }
            else if(b[i][j]=='G'){
                b[i][j]='Y';
            }
            else{
                break;
            }
        }
        for(int i=p+1,j=q-1;i<N&&j>=0;i++,j--){
            if(b[i][j]=='B'){
                b[i][j]='X';
            }
            else if(b[i][j]=='G'){
                b[i][j]='Y';
            }
            else{
                break;
            }
        }
    }
    else{
        for(int i=p,j=q;i>=0&&j>=0;i--,j--){
            if(b[i][j]=='Y'){
                b[i][j]='X';
            }
            else if(b[i][j]=='G'){
                b[i][j]='B';
            }
            else{
                break;
            }
        }
        for(int i=p+1,j=q+1;i<N&&j<M;i++,j++){
            if(b[i][j]=='Y'){
                b[i][j]='X';
            }
            else if(b[i][j]=='G'){
                b[i][j]='B';
            }
            else{
                break;
            }
        }
    }
}
int main(){
    int N,M;
    cin>>N>>M;
    vector<vector<char>> board(N,vector<char>(M));
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            cin>>board[i][j];
        }
    }
    int count=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(board[i][j]=='B'){
                count++;
                removecolor(board,i,j,'B');
            }
            else if(board[i][j]=='Y'){
                count++;
                removecolor(board,i,j,'Y');
            }
            else if(board[i][j]=='G'){
                count++;
                removecolor(board,i,j,'B');
                count++;
                removecolor(board,i,j,'Y');
            }
            else{
                continue;
            }
        }
    }
    cout << count<<endl;
    return 0;
}


编辑于 2020-02-26 21:29:56 回复(0)
import sys
raw_input = []
rows, cols = map(int, sys.stdin.readline().split())
for line in sys.stdin:
    raw_input.append(line.rstrip())
mydic = {'Y':[], 'B':[]}
for row in range(rows):
    for col in range(cols):
        if raw_input[row][col] == 'G':
            mydic['Y'].append([row, col])
            mydic['B'].append([row, col])
        elif raw_input[row][col] != 'X':
            mydic[raw_input[row][col]].append([row, col])

if __name__ == '__main__':
    res = 0
    def func(pos, f):
        pivot = pos.pop(0)
        tmp = []
        while pos:
            ele = pos.pop(0)
            if ele[0]-pivot[0] == 1 and ((f == 'B' and pivot[1]-ele[1] == 1) or (f == 'Y' and ele[1]-pivot[1] == 1)):
                pivot = ele
            else:
                tmp.append(ele)
        return tmp
    while mydic['Y'] or mydic['B']:
        if mydic['Y']:
            res += 1
            mydic['Y'] = func(mydic['Y'], 'Y')
        if mydic['B']:
            res += 1
            mydic['B'] = func(mydic['B'], 'B')
    print(res)
我们记录下Y和B的坐标
无需关注G的画法其实
遇见G的话直接在Y和B的坐标集中同时添加G的坐标就行了
之后可以对Y的坐标集和B的坐标集分别处理
pop出第一个坐标
在剩下的坐标中寻找连续且处于同一个斜对角线上的元素,满足的全部pop出
最后可得答案
发表于 2019-08-29 18:43:31 回复(0)
 #include <iostream>
#include <vector>
using namespace std;
char r;

vector<vector<int>> check_B(int i, int j, vector<vector<int>> A)
{
    A[i][j]--;
    int N = A.size();
    int M = A[0].size();
    int p = i - 1;
    int q = j + 1;
    while (p >= 0 && q < M)
    {
        if (A[p][q] == 1 || A[p][q] == 3)
        {
            A[p][q]--;
            p--; q++;
        }
        else
            break;
    }
    p = i + 1;
    q = j - 1;
    while (p < N&&q >= 0)
    {
        if (A[p][q] == 1 || A[p][q] == 3)
        {
            A[p][q]--;
            p++; q--;
        }
        else
            break;
    }
    return A;
}

vector<vector<int>> check_Y(int i, int j, vector<vector<int>> A)
{
    A[i][j]--;
    int N = A.size();
    int M = A[0].size();
    int p = i - 1;
    int q = j - 1;
    while (p >= 0 && q >= 0)
    {
        if (A[p][q] == 2 || A[p][q] == 3)
        {
            A[p][q] -= 2;
            p--; q--;
        }
        else
            break;
    }
    p = i + 1;
    q = j + 1;
    while (p < N&&q < M)
    {
        if (A[p][q] == 2 || A[p][q] == 3)
        {
            A[p][q] -= 2;
            p++; q++;
        }
        else
            break;
    }
    return A;
}

int main()
{
    int N, M;
    while (cin >> N >> M)
    {    
        vector<vector<int>> A (N, vector<int>(M, 0));
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < M; j++)
            {
                char c;
                cin >> c;
                if (c == 'X')
                    A[i][j] = 0;
                else if (c == 'B')
                    A[i][j] = 1;
                else if (c == 'Y')
                    A[i][j] = 2;
                else if (c == 'G')
                    A[i][j] = 3;
            }
        }

        int total_num = 0;
        
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < M; j++)
            {
                if (A[i][j] == 1 || A[i][j] == 3)
                {
                    A = check_B(i, j, A);
                    total_num++;
                }
                if (A[i][j] == 2)
                {
                    A = check_Y(i, j, A);
                    total_num++;
                }
            }
        }
        cout << total_num << endl;
    }
    return 0;
}

发表于 2019-02-12 01:06:10 回复(0)
#include<vector>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<cstdint>
#include<map>
#include<algorithm>
#include<string.h>
#include<unistd.h>
#include<set>

void FindInfo(std::vector<std::string> draw_board,short N,short M,
    char key,std::multimap<short,short>& ret){
        
    for(int m=0;m<N;m++){        
        for(int n=0;n<M;n++){
            
            if(draw_board[m][n]==key)
                
                ret.emplace(m,n);
        }
        
    }    
}

void CaculateDraw(std::vector<std::string> draw_board,short N,short M){
    
    std::multimap<short,short> ret;
    short x=0,y=0;
    int count=0;
    
    //x    
    FindInfo(draw_board,N,M,'B',ret);
    FindInfo(draw_board,N,M,'G',ret);
    for(auto iter=ret.begin();iter!=ret.end();iter++){
        
        //std::cout<<iter->first<<" "<<iter->second<<"\n";
        x=iter->first+1;
        y=iter->second+1;
                
        while(true){
            auto pos=std::find_if(ret.begin(),ret.end(),
            [=](const std::pair<short,short>& va){
                bool flag=false;
                if(x==va.first && y==va.second)
                    flag=true;
                return flag;
                
            });
            if(pos!=ret.end()){                
                x++;
                y++;
                ret.erase(pos);                    
                    
            }else{
                break;
            }
        }    
        ret.erase(iter);
        count++;
    }
    
    //y
    ret.clear();
    FindInfo(draw_board,N,M,'Y',ret);
    FindInfo(draw_board,N,M,'G',ret);
    for(auto iter=ret.begin();iter!=ret.end();iter++){
        
        x=iter->first+1;
        y=iter->second-1;
                
        while(true){
            auto pos=std::find_if(ret.begin(),ret.end(),
                [=](const std::pair<short,short>& va){
                    bool flag=false;
                    if(x==va.first && y==va.second)
                        flag=true;
                    return flag;
                });
            if(pos!=ret.end()){
                
                    x++;
                    y--;
                    ret.erase(pos);                    
                    
            }else{
                break;
            }
        }    
        ret.erase(iter);
        count++;
    }    
    std::cout<<count<<"\n";
}

void Draw(){
    
    short N=0,M=0,i=0;
    std::vector<std::string> draw_board;
    std::string draw_buf;
    std::cin>>N>>M;
    std::getline(std::cin,draw_buf); // must add this line 
    while(N-i){        
        std::getline(std::cin,draw_buf);
        draw_board.emplace_back(draw_buf);
        draw_buf.clear();
        i++;
        
    }
    std::reverse(draw_board.begin(),draw_board.end());
    CaculateDraw(draw_board,N,M);
}

int main(){
    
    Draw();
}

发表于 2018-08-21 18:00:27 回复(1)
一次遍历即可,时间复杂度O(N*M)。
因为'Y'只会以斜率 -1 出现,'B'只会以斜率 1 出现,所以这道题就变得十分简单。直接逐行逐列遍历,对于第 i 行第 j 列的元素 T[i][j],分析一下它的几种可能性如下:
1、T[i][j] == 'Y',此时只需看看它的左上角元素是否也为 'Y' or 'G' 即可,如果是,那么该元素可以被上面的元素以同一笔绘制而成,否则,需要新起一笔,cnt += 1;
2、T[i][j] == 'B',观察它的右上角元素是否也为 'B' or 'G' 即可,如若不是,cnt += 1;
3、T[i][j] == 'G',把上面两步都过一遍即可。
最后的 cnt 记录的便是最少用的笔数。
N, M = map(int, input().strip().split())
T = []
for i in range(N):
    T.append(input().strip())

cnt = 0
for i in range(N):
    for j in range(M):
        if T[i][j] == 'X': continue
        if T[i][j] in ['Y', 'G']:
            if i - 1 >= 0 and j - 1 >= 0 and T[i-1][j-1] in ['Y', 'G']: cnt += 0
            else: cnt += 1
        if T[i][j] in ['B', 'G']:
            if i - 1 >= 0 and j + 1 < M and T[i-1][j+1] in ['B', 'G']: cnt += 0
            else: cnt += 1
print(cnt)


发表于 2020-08-26 19:59:19 回复(4)
import java.util.Arrays;
import java.util.Scanner;

public class DrawerQ {

    public static int count = 0;

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int m = sc.nextInt();
            char[][] chs = new char[n][m];
            char[][] temp = new char[n][m];
            for (int i = 0; i < n; i++) {
                String s = sc.next();
                for (int j = 0; j < m; j++) {
                    chs[i][j] = s.charAt(j);
                }
                Arrays.fill(temp[i], 'X');
            }
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (chs[i][j] != temp[i][j]) {
                        if (chs[i][j] == 'Y' || (chs[i][j] == 'G' && temp[i][j] == 'B')) {
                            right(temp, chs, i, j);
                            count ++;
                        }else if (chs[i][j] == 'B' || (chs[i][j] == 'G' && temp[i][j] == 'Y')) {
                            left(temp, chs, i, j);
                            count ++;
                        }else if(chs[i][j] == 'G') {
                            right(temp, chs, i, j);
                            left(temp, chs, i, j);
                            count += 2;
                        }
                    }
                }
            }
            System.out.println(count);
        }
        sc.close();

    }

    public static void right(char[][] temp, char[][] chs, int i, int j) {
        while(i >= 0 && i < temp.length && j >= 0 && j < temp[0].length) {
            if (chs[i][j] == 'Y' && temp[i][j] == 'X') {
                temp[i][j] = 'Y';
            } else if (chs[i][j] == 'G') {
                if(temp[i][j] == 'B') {
                    temp[i][j] = 'G';
                }else if(temp[i][j] == 'X') {
                    temp[i][j] = 'Y';
                }
            } else {
                break;
            }
            i ++;
            j ++;
        }
    }

    public static void left(char[][] temp, char[][] chs, int i, int j) {
        while(i >= 0 && i < temp.length && j >= 0 && j < temp[0].length) {
            if (chs[i][j] == 'B' && temp[i][j] == 'X') {
                temp[i][j] = 'B';
            } else if (chs[i][j] == 'G') {
                if(temp[i][j] == 'Y') {
                    temp[i][j] = 'G';
                }else if(temp[i][j] == 'X'){
                    temp[i][j] = 'B';
                }
            } else {
                break;
            }
            i ++;
            j --;
        }
    }

}
发表于 2018-05-18 13:38:05 回复(1)
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,m;
    cin>>n>>m;
    vector<string> draw(n);
    for(int i=0;i<n;++i) cin>>draw[i];
    int cnt=0;
    int r,p;
    for(int i=0;i<n;++i)
        for(int j=0;j<m;++j)
        {
            if(draw[i][j]=='B')
            {
                for(r=0;i+r<n&&j-r>=0;++r)
                {
                    if(draw[i+r][j-r]=='B') draw[i+r][j-r]='X';
                    else if(draw[i+r][j-r]=='G') draw[i+r][j-r]='Y';
                    else break;
                }
                ++cnt;
            }
            else if(draw[i][j]=='Y')
            {
                for(p=0;i+p<n&&j+p<m;++p)
                {
                    if(draw[i+p][j+p]=='Y') draw[i+p][j+p]='X';
                    else if(draw[i+p][j+p]=='G') draw[i+p][j+p]='B';
                    else break;
                }
                ++cnt;
            }
            else if(draw[i][j]=='G')
            {
                for(r=0;i+r<n&&j-r>=0;++r)
                {
                    if(draw[i+r][j-r]=='B') draw[i+r][j-r]='X';
                    else if(draw[i+r][j-r]=='G') draw[i+r][j-r]='Y';
                    else break;
                }
                for(p=0;i+p<n&&j+p<m;++p)
                {
                    if(draw[i+p][j+p]=='Y') draw[i+p][j+p]='X';
                    else if(draw[i+p][j+p]=='G') draw[i+p][j+p]='B';
                    else break;
                }
                cnt+=2;
            }
        }
    cout<<cnt;
    return 0;
}
发表于 2021-08-17 16:53:06 回复(0)
'''
画家小Q又开始他的艺术创作。小Q拿出了一块有NxM像素格的画板, 画板初始状态是空白的,用'X'表示。
小Q有他独特的绘画技巧,每次小Q会选择一条斜线, 如果斜线的方向形如'/',即斜率为1,小Q会选择这条斜线中的一段格子,
都涂画为蓝色,用'B'表示;如果对角线的方向形如'\',即斜率为-1,小Q会选择这条斜线中的一段格子,都涂画为黄色,用'Y'表示。
如果一个格子既被蓝色涂画过又被黄色涂画过,那么这个格子就会变成绿色,用'G'表示。
小Q已经有想画出的作品的样子, 请你帮他计算一下他最少需要多少次操作完成这幅画。
'''

#获取输入
N, M = map(int, input().split()) # N*M的画板,N是长,M是宽
pad = [] # 画板,pad[N][M]
for n in range(N):
    pad.append(list(input())) # 'YXXB' -> ['Y', 'X', 'X', 'B']


#算法部分
res = 0
for n, row in enumerate(pad):
    for m, color in enumerate(row):
        if color=='Y'&nbs***bsp;color=='B':
            # print(pad)
            res += 1  # 如果不是空白,则肯定被画了一笔
        if color== 'G':
            res += 2
            pad[n][m] = 'X'
            # \掉Y
            tmp_n = n+1
            tmp_m = m+1
            if tmp_n==N&nbs***bsp;tmp_m==M: # 避免越界
                pass
            else:
                while pad[tmp_n][tmp_m]=='Y'&nbs***bsp;pad[tmp_n][tmp_m]=='G':
                    pad[tmp_n][tmp_m] = 'X' if pad[tmp_n][tmp_m]=='Y' else 'B'
                    tmp_n += 1
                    tmp_m += 1
                    if tmp_n==N&nbs***bsp;tmp_m==M: # 避免越界
                        break
            # /掉B
            tmp_n = n+1
            tmp_m = m-1
            if tmp_n==N&nbs***bsp;tmp_m==-1: # 避免越界
                pass
            else:
                while pad[tmp_n][tmp_m]=='B'&nbs***bsp;pad[tmp_n][tmp_m]=='G':
                    pad[tmp_n][tmp_m] = 'X' if pad[tmp_n][tmp_m]=='B' else 'Y'
                    tmp_n += 1
                    tmp_m -= 1
                    if tmp_n==N&nbs***bsp;tmp_m==-1: # 避免越界
                        break
            
        elif color=='Y': # \
            pad[n][m] = 'X'
            if m==M-1:   # 如果位于该行的最右边则轮到下一行
                continue
            tmp_n = n+1
            tmp_m = m+1
            if tmp_n==N&nbs***bsp;tmp_m==M: # 避免越界
                break
            while pad[tmp_n][tmp_m]=='Y'&nbs***bsp;pad[tmp_n][tmp_m]=='G':
                pad[tmp_n][tmp_m] = 'X' if pad[tmp_n][tmp_m]=='Y' else 'B'
                tmp_n += 1
                tmp_m += 1
                if tmp_n==N&nbs***bsp;tmp_m==M: # 避免越界
                    break
        elif color=='B': # /
            pad[n][m] = 'X'
            if m==0:     # 如果位于改行的第一个元素则轮到下一行
                continue
            tmp_n = n+1
            tmp_m = m-1
            if tmp_n==N&nbs***bsp;tmp_m==-1: # 避免越界
                break
            while pad[tmp_n][tmp_m]=='B'&nbs***bsp;pad[tmp_n][tmp_m]=='G':
                pad[tmp_n][tmp_m] = 'X' if pad[tmp_n][tmp_m]=='B' else 'Y'
                tmp_n += 1
                tmp_m -= 1
                if tmp_n==N&nbs***bsp;tmp_m==-1: # 避免越界
                    break
# 对最后一行进行捡漏
for color in pad[-1]:
    if color=='Y'&nbs***bsp;color=='B':
        res += 1
    elif color=='G':
        res += 2

#输出结果
print(res)









发表于 2021-05-08 23:57:39 回复(0)
import sys
def Blue(i, j):
    l[i][j] = 'X'
    while i+1 <= n-1 and j-1 >= 0:
        if l[i+1][j-1] == 'B':
            l[i+1][j-1] = 'X'
        elif l[i+1][j-1] == 'G':
            l[i+1][j-1] = 'Y'
        else:
            return
        i += 1
        j -= 1
def Yellow(i, j):
    l[i][j] = 'X'
    while i+1 <= n-1 and j+1 <= m-1:
        if l[i+1][j+1] == 'Y':
            l[i+1][j+1] = 'X'
        elif l[i+1][j+1] == 'G':
            l[i+1][j+1] = 'B'
        else:
            return
        i += 1
        j += 1
while True:
    s1 = sys.stdin.readline().strip()
    if not s1:
        break
    n, m = map(int, s1.split(" "))
    l = []
    for i in range(n):
        l.append(list(sys.stdin.readline().strip()))
    count = 0
    for i in range(n):
        for j in range(m):
            if l[i][j] == 'B':
                Blue(i, j)
                count += 1
            elif l[i][j] == 'Y':
                Yellow(i, j)
                count += 1
            elif l[i][j] == 'G':
                Blue(i, j)
                Yellow(i, j)
                count += 2
    print(count)

发表于 2020-09-05 14:57:09 回复(0)
#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
char c[55][55];

int main() {
    cin>>n>>m;
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=m ; ++j) {
            cin>>c[i][j];
        }
    }
    //遍历 \ 方向
    for (int i = 1; i <= n + m - 1; ++i) {
        int s=0; //0表示没落笔的状态,1表示落笔
        for (int j = 1; j <= n; ++j) {
            int k = j + m - i;
            if (1 <= k && k <= m) {
                if (c[j][k] == 'Y' || c[j][k] == 'G') {
                    if(!s){
                        ans++;s++;
                    }
                }
                else if(s)s--;
            }
        }
    }
    //遍历 / 方向
    for (int i = 2; i <= n + m ; ++i) {
        int s = 0; //同上
        for (int j = 1; j <= n; ++j) {
            int k = i - j;
            if (1 <= k && k <= m) {
                if (c[j][k] == 'B' || c[j][k] == 'G') {
                    if(!s){
                        ans++;s++;
                    }
                }
                else if(s)s--;
            }
        }
    }
    cout<<ans;
}

发表于 2020-08-24 23:06:14 回复(0)
['X', 'B', 'G', 'B', 'X']
['Y', 'B', 'B', 'Y', 'B']
['B', 'G', 'G', 'X', 'X']
['X', 'Y', 'Y', 'B', 'G']
['X', 'Y', 'B', 'G', 'G']
['Y', 'Y', 'X', 'Y', 'X']
这个我分left, right 之后是
left:
[0, 1, 1, 1, 0]
[0, 1, 1, 0, 1]
[1, 1, 1, 0, 0]
[0, 0, 0, 1, 1]
[0, 0, 1, 1, 1]
[0, 0, 0, 0, 0]
right:
[0, 0, 1, 0, 0]
[1, 0, 0, 1, 0]
[0, 1, 1, 0, 0]
[0, 1, 1, 0, 1]
[0, 1, 0, 1, 1]
[1, 1, 0, 1, 0]
不是应该16吗,为何是18?想不通
编辑于 2020-08-22 22:16:31 回复(0)
审题不认真想半天没想出来
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 52;
int paint[maxn][maxn];
enum{Y = 1, B};
int ans = 0;
void draw(int x, int y, int color)
{
    do{
        paint[x][y] ^= color;
        if(color == B)
            ++x,--y;
        else
            ++x,++y;
    }
    while(paint[x][y] & color);
    ++ans;
}

int main()
{
    memset(paint, 0, sizeof(paint));
    int n, m;
    char ch;
    scanf("%d %d",&n, &m);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
        {
            scanf(" %c", &ch);
            if(ch == 'G') paint[i][j] = 3;
            else if(ch == 'B') paint[i][j] = 2;
            else if(ch == 'Y') paint[i][j] = 1;
        }
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
        {
            if(paint[i][j] & Y) draw(i, j, Y);
            if(paint[i][j] & B) draw(i, j, B);
        }
    printf("%d\n", ans);
}


编辑于 2020-04-07 16:48:14 回复(0)

90% 通过率? 为什么啊
python 递归

n,m = map(int, input().split(" "))
L = []
for i in range(n):
    L.append(list(input().strip()))
def change(L, coordinate, target):
    n, m = len(L), len(L[0])
    i, j = coordinate
    L[i][j] = target
    if target == 'B':
        # left_dowm
        count = 1
        for r in range(i, min(n, i + j + 1)):
            l = i + j - r
            if L[r][l] == 'B':
                L[r][l] = 'X'
            elif L[r][l] == 'G':
                L[r][l] = 'Y'
            else:
                break
    elif target == 'Y':
        # right_down
        count = 1
        for r in range(i, min(n, m + i - j)):
            l = r - i + j
            if L[r][l] == 'Y':
                L[r][l] = 'X'
            elif L[r][l] == 'G':
                L[r][l] = 'B'
            else:
                break
    else:
        change(L, coordinate, 'B')
        change(L, coordinate, 'Y')
        count = 2
    return count
def painter(L):
    n, m = len(L), len(L[0])
    for i in range(n):
        for j in range(m):
            target = L[i][j]
            if target != 'X':
                count = change(L, [i, j],target)
                return count + painter(L)
    else:return 0
print(painter(L))


编辑于 2020-03-31 23:02:36 回复(0)