蓝桥杯Java-B组-第九届决赛-D_整理玩具:
题目:
小明有一套玩具,一共包含NxM个部件。这些部件摆放在一个包含NxM个小格子的玩具盒中, 每个小格子中恰好摆放一个部件。每一个部件上标记有一个0~9的整数 ,有可能有多个部件标记相同的整数。 小明对玩具的摆放有特殊的要求: 标记相同整数的部件必须摆在一起,组成一个矩形形状。 如以下摆放是满足要求的:00022
00033
44444
12244
12244
12233
01234
56789
以下摆放不满足要求:
11122
11122
33311
111111
122221
122221
111111
11122
11113
33333
给出一种摆放方式,请你判断是否符合小明的要求。
输入
输入包含多组数据。
第一行包含一个整数T,代表数据组数。 (1 <= T <= 10)
以下包含T组数据。
每组数据第一行包含两个整数N和M。 (1 <= N, M <= 10)
以下包含N行M列的矩阵,代表摆放方式。
输出
对于每组数据,输出YES或者NO代表是否符合小明的要求。
【样例输入】
3
3 5
00022
00033
44444
3 5
11122
11122
33311
2 5
01234
56789
【样例输出】
YES
NO
YES
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
解题思路:
1-变量创建:
(1).用来控制几组数据的整型变量x。
(2).用来控制每组数据行数的整形变量m,和控制列数的整形变量n。
(3).用来接收M和N的字符串数组变量s(原因下面有详解)
(4).用来接收每组数据中每一行的字符串数组变量str
(5).用来存放结果的布尔数组变量result
通过控制台获取相应的数据,然后对每一组数据进行判断,存放到result变量中,最后根据result的变量来输出相应的YES或者NO
2-解题难点:
重头戏:检查部分,用来检查这一组数据是不是符合摆放的标准
首先,我们需要找到一个能够判断是否为矩形的方法,实际上非常好理解,如果每一种类别的玩具需要存放到一起,那么从第一个数据到最后一个数据之间所构成的矩形框内,就不应该存在其他类型的玩具,比如:
00111
00011
00111
在这个摆放的方式中,我们按照上述的思路来查看是否合格,由于第一个“0”出现的位置是(0,0),最后一个“0”出现的位置是(2,1),那么在(0,0)-(2,1)这个矩形框内,没有出现其他的玩具类型,此时这组数据的摆放结果仍然为YES(不要误以为我们出现了错误),继续下去,第一个“1”出现的位置是(0,2)最后一个“1”出现的位置是(2,4),在(0,2)-(2,4)这个矩形框内,显然存在了玩具“0”,这就是不合格的,一旦出现一个不合格,那么这组数据就是NO
当然,如果每一种玩具的类型都只有一个,那么也是成立的,例如:
01234
56789
对于“0”而言(0,0)-(0,0)之间并没有其他的玩具类型
通过这两个例子,我们也可以发现我们是需要找到每一种玩具类型的初始点(第一次出现的地方)和结束点(最后一次出现的地方),这两个点的寻找就不必赘述了。
因此,我们通过框选矩形这种方法来判断某一组数据是否满足我们所需要的条件
细节点:控制台获取部分
如果我们按照如下的写法
package 蓝桥杯训练集;
import java.util.Scanner;
public class 控制台获取 {
public static void main(String[] args)
{
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
int x = in.nextInt();
for(int i=0;i<x;i++)
{
System.out.println("row"+i);
String str = in.nextLine();
}
}
}
控制台获取实例:
4
row0
row1
123
row2
456
row3
789
毫无疑问,我们总会少输入一行,具体原因鄙人也不太清楚,鄙人理解这可能是因为x在获取整形数值的时候没有遇到回车,当我们敲打回车的时候直接运行到了for里面,所以或直接从第1行而不是第0行开始获取值
解决方法:我们直接让x获取值的过程也通过一行来进行获取,因为整形是不可以获取一行数据的,所以我们添加了字符串变量,具体实现如下(这也是创建变量第三点的详解):
package 蓝桥杯训练集;
import java.util.Scanner;
public class 控制台获取 {
public static void main(String[] args)
{
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
String s1 = in.nextLine();
int x = Integer.valueOf(s1);
for(int i=0;i<x;i++)
{
System.out.println("row"+i);
String str = in.nextLine();
}
}
}
控制台获取实例:
4
row0
This is zero
row1
This is one
row2
This is two
row3
This is three
解决了以上两点问题,这个题就可以按照我们的思路来运行了
代码实现:
public class d_整理玩具 {
static int startx;
static int starty;//玩具起始点的坐标
static int endx;
static int endy;//玩具结束点的坐标
static int flage =0;//用来判断某一组数据是否符合规则
static int m;
static int n;//熟知的m和n,行和列
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);//实例化
String s1 = in.nextLine();//上述解决控制台获取的部分有详解
String[] s; //存放m和n的字符数组
int x = Integer.valueOf(s1);
boolean[] result = new boolean[x];//根据数据的数量来创建result变量
for(int i=0;i<x;i++){//接下来就是控制台获取了
s = in.nextLine().split(" ");
m=Integer.valueOf(s[0]);
n=Integer.valueOf(s[1]);
String[] str = new String[m];
for(int j=0;j<m;j++){
str[j] = in.nextLine();
}
int[][] map = new int [m][n];//创建存放数据的整形变量
for(int k=0;k<m;k++){//填充变量
for(int l=0;l<str[k].length();l++){
map[k][l]=Integer.valueOf(str[k].charAt(l)-48);//因为字符和数字相差48.所以要剪掉
}
}
if(checkzong(map)){//检查
result[i]=true;
}else {
result[i]=false;
}
}
for(boolean f:result){//增强for遍历,输出结果
if(f){
System.out.println("YES");
}else {
System.out.println("NO");
}
}
}
public static void checkstart(int x,int[][] map){//用来查找初始点
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(map[i][j]==x){
startx = i;
starty = j;
return ;
}
}
}
}
public static void checkend(int x,int[][] map){//用来查找结束点
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(map[i][j]==x){
endx = i;
endy = j;
}
}
}
}
public static boolean checktrue(int x,int startx,int starty,int endx,int endy,int[][] map)//用来判断这组数据是否合格,只判断x是否符合规则
{
for(int i=startx;i<=endx;i++){
for(int j=starty;j<endy;j++){
if(map[i][j]!=x){
return false;
}
}
}
return true;
}
public static boolean checkzong(int[][] map) {//用来对所有从0-9的玩具类型进行判断
flage =0;
for(int i=0;i<=9;i++){
startx=0;
starty=0;
endx=0;
endy=0;
checkstart(i,map);
checkend(i,map);
if(!checktrue(i,startx,starty,endx,endy,map)){
flage =1;
break;
}
}
if(flage==1){
return false;
}else {
return true;
}
}
}
代码或许有些繁琐,如若有更好的理解,敬待指点。^ . ^