目录
试题 A: 星期计算
本题总分:
5
分
【问题描述】
已知今天是星期六,请问
20
22
天后是星期几?
注意用数字
1
到
7
表示星期一到星期日。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
import java.math.BigInteger;
/**
* 星期计算
* 使用单层for循环
* @author HP
* @date 2022/04/28
*/
public class A_WeekCount {
public static void main(String[] args) {
BigInteger base = new BigInteger("20");
int power = 22;
BigInteger ans = new BigInteger("1");
for(int i = 1; i <= power; i++) {
ans = ans.multiply(base);
}
System.out.println(ans);
System.out.println(ans.mod(new BigInteger("7")));
}
}
试题 B: 山
本题总分:
5
分
【问题描述】
这天小明正在学数数。
他突然发现有些正整数的形状像一座“山”,比如
123565321
、
145541
,它
们左右对称(回文)且数位上的数字先单调不减,后单调不增。
小明数了很久也没有数完,他想让你告诉他在区间
[2022
,
2022222022]
中有
多少个数的形状像一座“山”。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
import java.math.BigInteger;
/**
* 星期计算
* 使用单层for循环
* @author HP
* @date 2022/04/28
*/
public class A_WeekCount {
public static void main(String[] args) {
BigInteger base = new BigInteger("20");
int power = 22;
BigInteger ans = new BigInteger("1");
for(int i = 1; ipublic class B_Mountain {
public static void main(String[] args) {
long start = 2022;
long end = 2022222022;
long ans = 0;
for (long i = start; i <= end; i++) {
if (check(i)){
ans++;
System.out.println(ans);
}
}
}
/**
* 检查是否是"山"
*
* @param i
* @return boolean
*/
public static boolean check(long i){
String string = String.valueOf(i);
StringBuilder stringBuilder = new StringBuilder(string);
if (string.equals(stringBuilder.reverse().toString()) == false){
return false;
}
for (int j = 0; j < string.length() / 2; j++) {
if (string.charAt(j) > string.charAt(j + 1)){
return false;
}
}
return true;
}
} <= power; i++) {
ans = ans.multiply(base);
}
System.out.println(ans);
System.out.println(ans.mod(new BigInteger("7")));
}
}
试题 C: 字符统计
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
10
分
【问题描述】
给定一个只包含大写字母的字符串
S
,请你输出其中出现次数最多的字母。
如果有多个字母均出现了最多次,按字母表顺序依次输出所有这些字母。
【输入格式】
一个只包含大写字母的字符串
S
.
【输出格式】
若干个大写字母,代表答案。
【样例输入】
BABBACAC
【样例输出】
AB
【评测用例规模与约定】
对于
100
%
的评测用例,
1
≤ |
S
| ≤
10
6
.
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeSet;
/**
* c字符统计
* 把每个字母出现的次数记录下来, 次数等于最大次数的字母输出
* @author HP
* @date 2022/04/28
*/
public class C_CharacterStatistics {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
scanner.close();
HashMap<Character, Integer> hashMap = new HashMap<>();
int max = 0;
for (int i = 0; i < string.length(); i++) {
Character character = string.charAt(i);
if (hashMap.containsKey(character)){
hashMap.put(character, hashMap.get(character) + 1);
}else {
hashMap.put(character, 1);
}
max = Math.max(max, hashMap.get(character));
}
TreeSet<Character> treeSet = new TreeSet<>();
for (Map.Entry<Character, Integer> entry: hashMap.entrySet()){
if (entry.getValue() == max){
treeSet.add(entry.getKey());
}
}
for (Character character: treeSet){
System.out.print(character);
}
}
}
试题 D: 最少刷题数
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
10
分
【问题描述】
小蓝老师教的编程课有
N
名学生,编号依次是
1
. . .
N
。第
i
号学生这学期
刷题的数量是
A
i
。
对于每一名学生,请你计算他至少还要再刷多少道题,才能使得全班刷题
比他多的学生数不超过刷题比他少的学生数。
【输入格式】
第一行包含一个正整数
N
。
第二行包含
N
个整数:
A
1
,
A
2
,
A
3
, . . . ,
A
N
.
【输出格式】
输出
N
个整数,依次表示第
1
. . .
N
号学生分别至少还要再刷多少道题。
【样例输入】
5
12 10 15 20 6
【样例输出】
0 3 0 0 7
【评测用例规模与约定】
对于
30
%
的数据,
1
≤
N
≤
1000
,
0
≤
A
i
≤
1000
.
对于
100
%
的数据,
1
≤
N
≤
100000
,
0
≤
A
i
≤
100000
.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
/**
* d最小数量问题
* 找出最小的数, 满足: 大于他的数的数量 <= 小于他的数的数量
* 如果是小于, 小于这个数的数在增加某个数后若有满足上述条件, 则增加之后要比这个数大1
* 否则, 增加之后等于这个数则可
* @author HP
* @date 2022/04/28
*/
public class D_MinimumNumberOfQuestions {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Integer> noSortArrayList = new ArrayList<>();
ArrayList<Integer> sortedArrayList = new ArrayList<>();
int n = scanner.nextInt();
for (int i = 0; i < n; i++) {
noSortArrayList.add(scanner.nextInt());
}
sortedArrayList.addAll(noSortArrayList);
sortedArrayList.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
Integer medium = 0;
int add = 0;
for (Integer integer: sortedArrayList){
medium = integer;
int start = sortedArrayList.indexOf(integer);
int end = sortedArrayList.lastIndexOf(integer);
int lessThan = start;
int moreThan = n - end - 1;
if (lessThan > moreThan){
break;
}
if (lessThan == moreThan){
add = 1;
break;
}
}
for (Integer integer: noSortArrayList){
if (integer < medium){
System.out.print(medium - integer + add);
}else{
System.out.print(0);
}
System.out.print(" ");
}
}
}
试题 E: 求阶乘
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
15
分
【问题描述】
满足
N
!
的末尾恰好有
K
个
0
的最小的
N
是多少
?
如果这样的
N
不存在输出
−
1
。
【输入格式】
一个整数
K
。
【输出格式】
一个整数代表答案。
【样例输入】
2
【样例输出】
10
【评测用例规模与约定】
对于
30
%
的数据,
1
≤
K
≤
10
6
.
对于
100
%
的数据,
1
≤
K
≤
10
18
.
import java.util.Scanner;
/**
* e找到!
* 采用二分法
* @author HP
* @date 2022/04/28
*/
public class E_FindTheFactorial {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
long left = 5;
long right = Long.MAX_VALUE;
long middle;
while (left != right){
middle = (left + right) / 2;
if (test(middle, n) >= n){
if (right != middle){
right = middle;
}else {
right = middle - 1;
}
}else{
if (left != middle){
left = middle;
}else {
left = middle + 1;
}
}
}
System.out.println((left / 5) * 5);
}
/**
* 测试
* 求 i 的阶乘有多少个0
* @param i 我
* @return long
*/
public static long test(long i, long n){
int ans = 0;
for (int j = 5; j <= i; j += 5) {
int k = j;
while (k % 5 == 0){
ans++;
k = k / 5;
if(ans >= n){
return ans;
}
}
}
return ans;
}
}
试题 F: 最大子矩阵
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
15
分
【问题描述】
小明有一个大小为
N
×
M
的矩阵,可以理解为一个
N
行
M
列的二维数组。
我们定义一个矩阵
m
的稳定度
f
(
m
)
为
f
(
m
) =
max
(
m
)
−
min
(
m
)
,其中
max
(
m
)
表示矩阵
m
中的最大值,
min
(
m
)
表示矩阵
m
中的最小值。现在小明想要从这
个矩阵中找到一个稳定度不大于
limit
的子矩阵,同时他还希望这个子矩阵的面
积越大越好(面积可以理解为矩阵中元素个数)。
子矩阵定义如下:从原矩阵中选择一组连续的行和一组连续的列,这些行
列交点上的元素组成的矩阵即为一个子矩阵。
【输入格式】
第一行输入两个整数
N
,
M
,表示矩阵的大小。
接下来
N
行,每行输入
M
个整数,表示这个矩阵。
最后一行输入一个整数
limit
,表示限制。
【输出格式】
输出一个整数,分别表示小明选择的子矩阵的最大面积。
【样例输入】
3 4
2 0 7 9
0 6 9 7
8 4 6 4
8
【样例输出】
6
【样例说明】
满足稳定度不大于
8
的且面积最大的子矩阵总共有三个,他们的面积都是
6
(粗体表示子矩阵元素):
2 0
7 9
0 6
9 7
8 4
6 4
2 0
7 9
0 6
9 7
8 4
6 4
2 0 7 9
0
6 9 7
8
4 6 4
【评测用例规模与约定】
评测用例编号
N
M
1, 2
1
≤
N
≤
10 1
≤
M
≤
10
3, 4
N
= 1
M
≤
100000
5
∼
12
1
≤
N
≤
10
M
≤
10000
13
∼
20
1
≤
N
≤
80 1
≤
M
≤
80
对于所有评测用例,
0
≤
矩阵元素值
,
limit
≤
10
5
。
import java.util.Scanner;
/**
* f最大子矩阵
* 搜索剪枝
* @author HP
* @date 2022/04/29
*/
public class F_MaximumSubmatrix {
static int row;
static int line;
static int limit;
static int area = 0;
static int[][] map;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
row = scanner.nextInt();
line = scanner.nextInt();
map = new int[row + 2][line + 2];
for (int i = 1; i <= row ; i++) {
for(int j = 1; j <= line; j++) {
map[i][j] = scanner.nextInt();
}
}
limit = scanner.nextInt();
scanner.close();
for(int row1 = 1; row1 <= row; row1++) {
for(int line1 = 1; line1 <= line; line1++) {
for(int row2 = row1; row2 <= row; row2++) {
for(int line2 = line1; line2 <= line; line2++) {
int tempAare = (row2 - row1 + 1) * (line2 - line1 + 1);
if (tempAare > area){
Calculate(tempAare, row1, line1, row2, line2);
}
}
}
}
}
System.out.println(area);
}
public static void Calculate(int tempArea, int row1, int line1, int row2, int line2){
int max = 0;
int min = Integer.MAX_VALUE;
for(int i = row1; i <= row2; i++) {
for(int j = line1; j <= line2; j++) {
max = Math.max(max, map[i][j]);
min = Math.min(min, map[i][j]);
}
}
if ((max - min) <= limit){
area = Math.max(area, tempArea);
}
}
}
试题 G: 数组切分
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
20
分
【问题描述】
已知一个长度为
N
的数组:
A
1
,
A
2
,
A
3
, ...
A
N
恰好是
1
∼
N
的一个排列。现
在要求你将
A
数组切分成若干个
(
最少一个,最多
N
个
)
连续的子数组,并且
每个子数组中包含的整数恰好可以组成一段连续的自然数。
例如对于
A
=
{
1
,
3
,
2
,
4
}
,
一共有
5
种切分方法:
{
1
}{
3
}{
2
}{
4
}
:每个单独的数显然是
(
长度为
1
的
)
一段连续的自然数
。
{
1
}{
3
,
2
}{
4
}
:
{
3
,
2
}
包含
2
到
3
,是
一段连续的自然数
,另外
{
1
}
和
{
4
}
显然
也是。
{
1
}{
3
,
2
,
4
}
:
{
3
,
2
,
4
}
包含
2
到
4
,是
一段连续的自然数
,另外
{
1
}
显然也是。
{
1
,
3
,
2
}{
4
}
:
{
1
,
3
,
2
}
包含
1
到
3
,是
一段连续的自然数
,另外
{
4
}
显然也是。
{
1
,
3
,
2
,
4
}
:只有一个子数组,包含
1
到
4
,是
一段连续的自然数
。
【输入格式】
第一行包含一个整数
N
。第二行包含
N
个整数,代表
A
数组。
【输出格式】
输出一个整数表示答案。由于答案可能很大,所以输出其对
1000000007
取
模后的值
【样例输入】
4
1 3 2 4
【样例输出】
5
对于
30
%
评测用例,
1
≤
N
≤
20
.
对于
100
%
评测用例,
1
≤
N
≤
10000
.
import java.util.Scanner;
/**
* g数组分割
* 分割到最后一个数时进行判断
* @author HP
* @date 2022/04/29
*/
public class G_ArraySegmentation {
static int length;
static int ans = 0;
static int[] list;
static int[] segmentation;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
length = scanner.nextInt();
list = new int[length + 1];
for(int i = 1; i <= length; i++) {
list[i] = scanner.nextInt();
}
segmentation = new int[length + 1];
segmentation[0] = 0;
grouping(0);
System.out.println(ans);
}
public static void grouping(int groupNumber){
for (int i = segmentation[groupNumber] + 1; i <= length; i++) {
segmentation[groupNumber + 1] = i;
if (i == length){
test(groupNumber + 1);
}else{
grouping(groupNumber + 1);
}
}
}
public static void test(int groupNumber){
for (int i = 1; i <= groupNumber; i++) {
int start = segmentation[i - 1];
int end = segmentation[i];
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int j = start + 1; j <= end; j++) {
max = Math.max(max, list[j]);
min = Math.min(min, list[j]);
}
if ((max - min + 1) == (end - start)){
continue;
}else{
return;
}
}
// 输出符合要求的分割
// for (int i = 0; i <= groupNumber; i++) {
// System.out.print(segmentation[i] + "\t");
// }
// System.out.println();
ans++;
}
}
试题 H: 回忆迷宫
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
20
分
【问题描述】
爱丽丝刚从一处地下迷宫中探险归来,你能根据她对于自己行动路径的回
忆,帮她画出迷宫地图吗?
迷宫地图是基于二维网格的。爱丽丝会告诉你一系列她在迷宫中的移动步
骤,每个移动步骤可能是上下左右四个方向中的一种,表示爱丽丝往这个方向
走了一格。你需要根据这些移动步骤给出一个迷宫地图,并满足以下条件:
1
、爱丽丝能在迷宫内的某个空地开始,顺利的走完她回忆的所有移动步
骤。
2
、迷宫内不存在爱丽丝没有走过的空地。
3
、迷宫是封闭的,即可通过墙分隔迷宫内与迷宫外。任意方向的无穷远处
视为迷宫外,所有不与迷宫外联通的空地都视为是迷宫内。(迷宫地图为四联
通,即只有上下左右视为联通)
4
、在满足前面三点的前提下,迷宫的墙的数量要尽可能少。
【输入格式】
第一行一个正整数
N
,表示爱丽丝回忆的步骤数量。
接下来一行
N
个英文字符,仅包含
UDLR
四种字符,分别表示上(
Up
)、
下(
Down
)、左(
Left
)、右(
Right
)。
【输出格式】
请通过字符画的形式输出迷宫地图。迷宫地图可能包含许多行,用字符
‘*’
表示墙,用
‘ ’
(空格)表示非墙。
你的输出需要保证以下条件:
1
、至少有一行第一个字符为
‘*’
。
2
、第一行至少有一个字符为
‘*’
。
3
、每一行的最后一个字符为
‘*’
。
4
、最后一行至少有一个字符为
‘*’
。
【样例输入】
17
UUUULLLLDDDDRRRRU
【样例输出】
*****
*
*
* *** *
* *** *
* *** *
*
*
*****
【样例说明】
爱丽丝可以把第六行第六个字符作为起点。
外墙墙墙墙墙外
墙内内内内内墙
墙内墙墙墙内墙
墙内墙墙墙内墙
墙内墙墙墙内墙
墙内内内内内墙
外墙墙墙墙墙外
【评测用例规模与约定】
对于所有数据,
0
<
N
≤
100
.
import java.util.Scanner;
/**
* h记忆迷宫
* 将路线周围设为墙
* @author HP
* @date 2022/04/29
*/
public class H_MemoryMaze {
static int maxStep = 100;
static int walkLange = 2 * maxStep + 1;
static int[][] walkingMap = new int[walkLange + 1][walkLange + 1];
static char[][] mazeMap = new char[walkLange + 1][walkLange + 1];
static int step;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
step = scanner.nextInt();
scanner.nextLine();
String string = scanner.nextLine();
scanner.close();
int x = maxStep + 1;
int y = maxStep + 1;
walkingMap[x][y] = 1;
for (int i = 0; i < string.length(); i++) {
char tempChar = string.charAt(i);
if (tempChar == 'U'){
x = x - 1;
}else if (tempChar == 'D'){
x = x + 1;
}else if (tempChar == 'L'){
y = y - 1;
}else {
y = y + 1;
}
System.out.println(x + " " + y);
walkingMap[x][y] = 1;
}
int firstRow = 0;
int lastRow = 0;
int firstLine = 0;
int lastLine = 0;
for (int i = 1; i <= walkLange; i++) {
for(int j = 1; j <= walkLange; j++) {
if (walkingMap[i][j] == 1){
firstRow = i;
break;
}
}
if (firstRow != 0){
break;
}
}
for (int i = walkLange; i >= 1; i--) {
for(int j = 1; j <= walkLange; j++) {
if (walkingMap[i][j] == 1){
lastRow = i;
break;
}
}
if (lastRow != 0){
break;
}
}
for (int i = 1; i <= walkLange; i++) {
for(int j = 1; j <= walkLange; j++) {
if (walkingMap[j][i] == 1){
firstLine = i;
break;
}
}
if (firstLine != 0){
break;
}
}
for (int i = walkLange; i >= 1; i--) {
for(int j = 1; j <= walkLange; j++) {
if (walkingMap[j][i] == 1){
lastLine = i;
break;
}
}
if (lastLine != 0){
break;
}
}
for (int i = firstRow; i <= lastRow; i++) {
for (int j = firstLine; j <= lastLine; j++) {
if (walkingMap[i][j] == 1){
if (walkingMap[i - 1][j] != 1){
walkingMap[i - 1][j] = 2;
}
if (walkingMap[i + 1][j] != 1){
walkingMap[i + 1][j] = 2;
}
if (walkingMap[i][j - 1] != 1){
walkingMap[i][j - 1] = 2;
}
if (walkingMap[i][j + 1] != 1){
walkingMap[i][j + 1] = 2;
}
}
}
}
for (int i = firstRow; i <= lastRow; i++) {
for (int j = firstLine; j <= lastLine; j++) {
if(check(i, j)){
walkingMap[i][j] = 2;
}
}
}
for (int i = firstRow - 1; i <= lastRow + 1; i++) {
for (int j = firstLine - 1; j <= lastLine + 1; j++) {
if (walkingMap[i][j] == 2){
mazeMap[i][j] = '*';
}else{
mazeMap[i][j] = ' ';
}
}
}
for (int i = firstRow - 1; i <= lastRow + 1; i++) {
for (int j = firstLine - 1; j <= lastLine + 1; j++) {
System.out.print(mazeMap[i][j]);
}
System.out.println();
}
}
/**
* 检查
* 检查这个格子是否被墙围着, 且不是路线, 将这个格子设为墙
* @param i 我
* @param j j
* @return boolean
*/
public static boolean check(int i, int j){
if (walkingMap[i][j] == 1){
return false;
}
if (walkingMap[i][j] == 2){
return true;
}
if(i == walkLange || i == 1 || j == walkLange || j == 1){
return false;
}
return (check(i - 1, j) && check(i + 1, j) && check(i, j - 1) && check(i, j + 1));
}
}
试题 I: 红绿灯
时间限制
: 1.0s
内存限制
: 512.0MB
本题总分:
25
分
【问题描述】
爱丽丝要开车去上班,上班的路上有许多红绿灯,这让爱丽丝很难过。为
了上班不迟到,她给自己的车安装了氮气喷射装置。现在她想知道自己上班最
短需要多少时间。
爱丽丝的车最高速度是
1
V
米每秒,并且经过改装后,可以瞬间加速到小于
等于最高速的任意速度,也可以瞬间停止。
爱丽丝家离公司有
N
米远,路上有
M
个红绿灯,第
i
个红绿灯位于离爱
丽丝家
A
i
米远的位置,绿灯持续
B
i
秒,红灯持续
C
i
秒。在初始时(爱丽丝开
始计时的瞬间),所有红绿灯都恰好从红灯变为绿灯。如果爱丽丝在绿灯变红的
瞬间到达红绿灯,她会停下车等红灯,因为她是遵纪守法的好市民。
氮气喷射装置可以让爱丽丝的车瞬间加速到超光速(且不受相对论效应的
影响!),达到瞬移的效果,但是爱丽丝是遵纪守法的好市民,在每个红绿灯前
她都会停下氮气喷射,即使是绿灯,因为红绿灯处有斑马线,而使用氮气喷射
装置通过斑马线是违法的。此外,氮气喷射装置不能连续启动,需要一定时间
的冷却,表现为通过
K
个红绿灯后才能再次使用。(也就是说,如果
K
= 1
,就
能一直使用啦!)初始时,氮气喷射装置处于可用状态。
【输入格式】
第一行四个正整数
N
、
M
、
K
、
V
,含义如题面所述。
接下来
M
行,每行三个正整数
A
i
、
B
i
、
C
i
,含义如题面所述。
【输出格式】
输出一个正整数
T
,表示爱丽丝到达公司最短需要多少秒。
【样例输入】
90 2 2 2
30 20 20
60 20 20
【样例输出】
80
【样例说明】
爱丽丝在最开始直接使用氮气喷射装置瞬间到达第一个红绿灯,然后绿灯
通过,以最高速行进
60
秒后到达第二个红绿灯,此时绿灯刚好变红,于是她等
待
20
秒再次变为绿灯后通过该红绿灯,此时氮气喷射装置冷却完毕,爱丽丝再
次使用瞬间到达公司,总共用时
80
秒。
【评测用例规模与约定】
对于
30
%
的数据,
N
≤
100;
M
≤
10;
M
<
K
;
V
= 1
.
对于
60
%
的数据,
N
≤
1000;
M
≤
100;
K
≤
50;
B
i
,
C
i
≤
100;
V
≤
10
.
对于
100
%
的数据,
0
<
N
≤
10
8
;
M
≤
1000;
K
≤
1000; 0
<
B
i
,
C
i
≤
10
6
; 0
<
V
≤
10
6
; 0
<
A
i
<
N
;
对任意
i
<
j
,
有
A
i
<
A
j
.
试题 J: 拉箱子
时间限制
: 1.0s
内存限制
: 1.0GB
本题总分:
25
分
【问题描述】
推箱子是一款经典电子游戏,爱丽丝很喜欢玩,但是她有点玩腻了,现在
她想设计一款拉箱子游戏。
拉箱子游戏需要玩家在一个
N
×
M
的网格地图中,控制小人上下左右移动,
将箱子拉到终点以获得胜利。
现在爱丽丝想知道,在给定地形(即所有墙的位置)的情况下,有多少种
不同的可解的初始局面。
【初始局面】
的定义如下:
1
、初始局面由排列成
N
×
M
矩形网格状的各种元素组成,每个网格中有
且只有一种元素。可能的元素有:空地、墙、小人、箱子、终点。
2
、初始局面中有且只有一个小人。
3
、初始局面中有且只有一个箱子。
4
、初始局面中有且只有一个终点。
【可解】
的定义如下:
通过有限次数的移动小人(可以在移动的同时拉箱子),箱子能够到达终点
所在的网格。
【移动】
的定义如下:
在一次移动中,小人可以移动到相邻(上、下、左、右四种选项)的一个
网格中,前提是满足以下条件:
1
、小人永远不能移动到
N
×
M
的网格外部。
2
、小人永远不能移动到墙上或是箱子上。
3
、小人可以移动到空地或是终点上。
【拉箱子】
的定义如下:
在一次合法移动的同时,如果小人初始所在网格沿小人移动方向的反方向
上的相邻网格上恰好是箱子,小人可以拉动箱子一起移动,让箱子移动到小人
初始所在网格。
即使满足条件,小人也可以只移动而不拉箱子。
【输入格式】
第一行两个正整数
N
和
M
,表示网格的大小。
接下来
N
行,每行
M
个由空格隔开的整数
0
或
1
描述给定的地形。其中
1
表示墙,
0
表示未知的元素,未知元素可能是小人或箱子或空地或终点,但不
能是墙。
【输出格式】
输出一个正整数,表示可解的初始局面数量。
【样例输入】
2 4
0 0 0 0
1 1 1 0
【样例输出】
13
【样例说明】
13
种可解的初始局面示意图如下:
人终箱空
墙墙墙空
********
人终空箱
墙墙墙空
********
人空终箱
墙墙墙空
********
箱人终空
墙墙墙空
********
空人终箱
墙墙墙空
********
箱终人空
墙墙墙空
********
空终人箱
墙墙墙空
********
箱终空人
墙墙墙空
********
箱空终人
墙墙墙空
********
空箱终人
墙墙墙空
********
箱终空空
墙墙墙人
********
箱空终空
墙墙墙人
********
空箱终空
墙墙墙人
【评测用例规模与约定】
对于
30
%
的数据,
N
,
M
≤
3
.
对于
100
%
的数据,
0
<
N
,
M
≤
10
.