第八届蓝桥杯(2017年)JavaA组省赛真题解析
- 1.迷宫
- X星球的一处迷宫游乐园建在某个小山坡上,
- 它是由10*10相互联通的小房间组成,房间的地板上写着很大的字母,
- 我们假设玩家是面超着上坡的方向战立,则
- L表示走到左边的房间
- R表示走到右边的额房间
- U表示走向上坡方向的房间
- D表示走到下坡方向的房间
- 100位玩家,你算一下最后又有多少个能走出迷宫?
方式1:搜索+标记
public class Main {
static int cnt = 0 ;
static int [][] vis = new int [10][10] ;
public static void main(String[] args) {
char[][] a = {
{'U','D','D','L','U','U','L','R','U','L'},
{'U','U','R','L','L','L','R','R','R','U'},
{'R','R','U','U','R','L','D','L','R','D'},
{'R','U','D','D','D','D','U','U','U','U'},
{'U','R','U','D','L','L','R','R','U','U'},
{'D','U','R','L','R','L','D','L','R','L'},
{'U','L','L','U','R','L','L','R','D','U'},
{'R','D','L','U','L','L','R','D','D','D'},
{'U','U','D','D','U','D','U','D','L','L'},
{'U','L','R','D','L','U','U','R','R','R'},
};
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
boolean res = dfs(a, i, j) ;
if(res){
cnt ++ ;
clear(vis) ;
}
}
}
System.out.println(cnt);
}
private static void clear(int[][] vis) {
for(int i=0; i<vis.length; i++){
for(int j=0; j<vis[0].length; j++){
vis[i][j] = 0 ;
}
}
}
private static boolean dfs(char[][] a, int i, int j) {
if(i<0 || j<0 || i>9 || j>9){
return true ;
}
if(vis[i][j] == 1){
return false ;
}
vis[i][j] = 1 ;
switch (a[i][j]){
case 'U': return dfs(a, i-1, j) ;
case 'D': return dfs(a, i+1, j) ;
case 'L': return dfs(a, i, j-1) ;
case 'R': return dfs(a, i, j+1) ;
default: return false ;
}
}
}
方式2:
/**
* 1.迷宫
* X星球的一处迷宫游乐园建在某个小山坡上,
* 它是由10*10相互联通的小房间组成,房间的地板上写着很大的字母,
* 我们假设玩家是面超着上坡的方向战立,则
* L表示走到左边的房间
* R表示走到右边的额房间
* U表示走向上坡方向的房间
* D表示走到下坡方向的房间
* 100位玩家,你算一下最后又有多少个能走出迷宫?
*/
public class Main1 {
static int cnt = 0 ;
static int [][] vis = new int [10][10] ;
public static void main(String[] args) {
char[][] a = {
{'U','D','D','L','U','U','L','R','U','L'},
{'U','U','R','L','L','L','R','R','R','U'},
{'R','R','U','U','R','L','D','L','R','D'},
{'R','U','D','D','D','D','U','U','U','U'},
{'U','R','U','D','L','L','R','R','U','U'},
{'D','U','R','L','R','L','D','L','R','L'},
{'U','L','L','U','R','L','L','R','D','U'},
{'R','D','L','U','L','L','R','D','D','D'},
{'U','U','D','D','U','D','U','D','L','L'},
{'U','L','R','D','L','U','U','R','R','R'},
};
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
dfs(a, i, j) ;
}
}
System.out.println(cnt);
}
private static void clear(int[][] vis) {
for(int i=0; i<vis.length; i++){
for(int j=0; j<vis[0].length; j++){
vis[i][j] = 0 ;
}
}
}
private static void dfs(char[][] a, int i, int j) {
if(i<0 || j<0 || i>9 || j>9){
cnt ++ ;
clear(vis);
return ;
}
if(vis[i][j] == 1){
clear(vis);
return ;
}
vis[i][j] = 1 ;
if(a[i][j] == 'U'){
dfs(a, i-1, j) ;
}
if(a[i][j] == 'D'){
dfs(a, i+1, j) ;
}
if(a[i][j] == 'L'){
dfs(a, i, j-1) ;
}
if(a[i][j] == 'R'){
dfs(a, i, j+1) ;
}
}
}
- 9数算式
全排列划分区间计算
/**
* 9数算式
*/
import java.util.Arrays;
public class Main {
//最后要除2
static int [] a ;
static int cnt = 0 ;
public static void main(String[] args) {
a = new int[] {1,2,3,4,5,6,7,8,9} ;
f(a, 0) ;
System.out.println(cnt/2);
}
private static void f(int[] a, int k) { //全排列
if(k==a.length){
check(a) ;
}
for(int j=k; j<a.length; j++){
swap(a, j, k) ;
f(a, k+1) ;
swap(a, j, k) ;
}
}
private static void swap(int [] a, int i, int j){
int temp = a[i] ;
a[i] = a[j] ;
a[j] = temp ;
}
private static void check(int [] a) { //第每个排列判断,并计数
for(int j=1; j<a.length; j++){
int pre = compute(a, 0, j) ;
int pos = compute(a, j, a.length) ;
int value = pre * pos ;
if(judge(value)){
cnt ++ ;
}
}
}
private static int compute(int[] a, int x, int y) {
int sum = 0 ;
for(int i=x; i<y; i++){
sum = sum * 10 + a[i] ;
}
return sum ;
}
private static boolean judge(int value) {
String s = String.valueOf(value);
char [] r = s.toCharArray() ;
Arrays.sort(r);
String s1 = String.valueOf(r) ;
return s1.equals("123456789") ;
}
}
3.魔方状态
略
- 4.方格分割
- 6*6的方格,沿着格子的边线剪成两部分,要求这两部分完全相同,
- 一共有多少种分割方法,旋转对称的属于同一种方法。
/**
* 4.方格分割
* 6*6的方格,沿着格子的边线剪成两部分,要求这两部分完全相同,
* 一共有多少种分割方法,旋转对称的属于同一种方法。
*
*/
public class Main {
static int cnt = 0 ;
static int [] offsetX = {-1,1,0,0} ;
static int [] offsetY = {0,0,-1,1} ;
static int [][] vis = new int [7][7] ;
public static void main(String[] args) {
dfs(3, 3) ;
System.out.println(cnt/4);
}
private static void dfs(int x, int y) {
if(x==0 || y==0 || x==6 || y==6){
cnt ++ ;
return ;
}
vis[x][y] = 1 ;
vis[6-x][6-y] = 1 ;
for(int i=0; i<4; i++){
int nx = offsetX[i] + x ;
int ny = offsetY[i] + y ;
if(nx<0 || ny<0 || nx>6 || ny>6){
continue;
}
if(vis[nx][ny] != 1){
dfs(nx, ny);
}
}
vis[x][y] = 0 ;
vis[6-x][6-y] = 0 ;
}
}
5,6代码填空,略
- 7.正则问题
- 考虑一种简单的正则表达式,只有x()|组成的正则表达式,
- 小明想求出这个正则表达式能接受的最长字符串的长度。
- 输入正则表达式,输出这个正则表达式能接收的最长字符串的长度。
import java.util.Scanner;
/**
* 7.正则问题
* 考虑一种简单的正则表达式,只有x()|组成的正则表达式,
* 小明想求出这个正则表达式能接受的最长字符串的长度。
* 输入正则表达式,输出这个正则表达式能接收的最长字符串的长度。
*
*/
public class Main {
static String s ;
static int cnt = 0 ;
static int len ;
static int pos = 0 ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
s = input.next() ;
len = s.length() ;
cnt = f() ;
System.out.println(cnt);
}
private static int f() {
int temp = 0 ; //保存连续的x数量
int m = 0;
while(pos < len){
if(s.charAt(pos) == '('){
pos ++ ;
temp += f() ; //等待结果,并累加到cnt
}else if(s.charAt(pos) == 'x'){
pos ++ ;
temp ++ ;
}else if(s.charAt(pos) == '|'){
pos ++ ;
m = Math.max(m, temp) ;
temp = 0 ;
}else if(s.charAt(pos) == ')'){
pos ++ ;
m = Math.max(m, temp) ;
return m ;
}
}
m = Math.max(m, temp);
return m ;
}
}
- 8.包子凑数
import java.util.Scanner;
/**
*/
public class Main {
static int n ;
static int [] a ;
static int cnt = 0 ;
static int g ;
static boolean [] f = new boolean[10000] ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
n = input.nextInt() ;
f[0] = true ;
a = new int [n] ;
for(int i=0; i<n; i++){
a[i] = input.nextInt() ;
if(i==0){
g = a[i] ;
}else{
g = gcd(g, a[i]) ;
}
for(int j=0; j+a[i]<10000; j++){
if(f[j]){
f[j+a[i]] = true ;
}
}
}
if(g!=1){
System.out.println("INF");
}else {
for(int i=0; i<10000; i++){
if(!f[i]){
cnt ++ ;
//System.out.println(i);
}
}
System.out.println(cnt);
}
}
private static int gcd(int m, int n) {
if(n == 0){
return m ;
}else{
return gcd(n, m%n) ;
}
}
}
/**
- 9.分巧克力
- 儿童节会有K位小朋友到小明家里做客,小明拿出珍藏的巧克力招待小朋友们,
- 小明一共有N块巧克力,其中第i块是Hi×Wi的方格组成的长方形。
- 小明需要从N块巧克力中切出K块分给小朋友,切出的巧克力要满足:
- 1.形状是正方形,边长是整数
- 2.大小相同
- 例如一块6×5的巧克力可以切除6块2×2的巧克力或者2块3×3的巧克力。
*/
方法1:暴力枚举法
import java.util.Scanner;
/**
* 方法1:暴力枚举法
*/
public class Main {
static int N, K, cnt = 0 ;
static int [] H ;
static int [] W ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
N = input.nextInt() ;
K = input.nextInt() ;
H = new int [N] ;
W = new int [N] ;
for(int i=0; i<N; i++){
H[i] = input.nextInt() ;
W[i] = input.nextInt() ;
}
int len = 100000 ;
for(int i=len;i>=1 ; i--){
for(int j=0; j<N; j++) {
cnt += (H[j] / i) * (W[j] / i) ;
}
if(cnt >= K){
System.out.println(i);
break ;
}
}
}
}
方法2:二分法优化暴力枚举
import java.util.Scanner;
public class Main1 {
static int N , K, cnt = 0 ;
static int [] H ;
static int [] W ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
N = input.nextInt() ;
K = input.nextInt() ;
H = new int [N] ;
W = new int [N] ;
for(int i=0; i<N; i++){
H[i] = input.nextInt() ;
W[i] = input.nextInt() ;
}
int l = 1, r = 100001 ;
while(l<=r){ //二分法优化暴力枚举
int mid = (l+r)>>1 ;
int sum = 0 ;
for(int i=0; i<N; i++){
sum += (H[i] / mid) * (H[i] / mid) ;
}
if(sum >= K){
l = mid + 1 ;
cnt = mid ;
}else{
r = mid - 1 ;
}
}
System.out.println(cnt);
}
}
- 10.油漆面积
- 矩阵的格式表示为(x1,y1,x2,y2),代表两个矩阵的对角点坐标
- 所有机器人选中的矩形区域涂上黄色油漆,
- 计算一下,一共耗费多少油漆,只需要计算所有矩形的覆盖面积有多大就可以
- 注意:各个矩形可能会重叠。
- 要求:输入为若干矩阵,输出为面积总和。
- 输入:
- 3
- 1 5 10 10
- 3 1 20 20
- 2 7 15 17
- 输出:
- 340
*输入: - 3
- 5 2 10 6
- 2 7 12 10
- 8 1 15 15
- 输出:
- 128
扫描标记法:
import java.util.Scanner;
public class Main {
static int n, cnt = 0 ;
static boolean [][] vis = new boolean[10000][10000] ;
public static void main(String[] args) {
Scanner input = new Scanner(System.in) ;
n = input.nextInt() ;
for(int i=0; i<n; i++){
int x1 = input.nextInt() ;
int y1 = input.nextInt() ;
int x2 = input.nextInt() ;
int y2 = input.nextInt() ;
for(int j=x1; j<x2; j++){
for(int k=y1; k<y2; k++){
vis[j][k] = true ;
}
}
}
for(int i=0; i<10000;i++){
for(int j=0; j<10000; j++){
if(vis[i][j]){
cnt ++ ;
}
}
}
System.out.println(cnt);
}
}
线段树+扫描线法