题目背景
题目描述
输入格式
输出格式
输出到标准输出。
每个查询操作输出一行,仅包含一个整数表示查询结果。
样例1输入
3 2 3
1 2
3 4
5 6
3 0 1
1 2 3
3 1 2
样例1输出
2
6
样例2输入
3 2 5
1 2
3 4
5 6
3 1 0
2 0 0
3 1 0
1 3 2
3 1 0
样例2输出
3
2
5
子任务
提示
-
对于 n×m 的矩阵,虽然转置和重塑操作都可以将矩阵形态变为 m×n,但这两种操作通常会导致不同的结果。
代码一(过80%)
import java.util.Scanner;
class Main {
static int n, m;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int t = scanner.nextInt();
// 读入矩阵
int[][] matrix = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = scanner.nextInt();
}
}
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (a == 1) {
matrix = rebuild(matrix, b, c);
} else if (a == 2) {
matrix = transpose(matrix);
} else {
System.out.println(matrix[b][c]);
}
}
}
// 转置
private static int[][] transpose(int[][] matrix) {
int[][] matrix2 = new int[m][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[j][i] = matrix[i][j];
}
}
int temp = n;
n = m;
m = temp;
return matrix2;
}
// 重塑
private static int[][] rebuild(int[][] matrix, int p, int q) {
int[][] matrix2 = new int[p][q];
// 下标指针
int pp = 0, qq = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[i][j];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
n = p;
m = q;
return matrix2;
}
}
很直接的转换方式,只过了80%的测试样例,剩下20%超时,说明需要优化时间复杂度。
子任务也说明了80%的是小数据,剩下的20%是大数据。
代码二(过80%)
将转置优化掉了,改用一个boolean变量判断。但是还是超时。
import java.util.Scanner;
class Main {
static int n, m;
static boolean isTransed = false;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int t = scanner.nextInt();
// 读入矩阵
int[][] matrix = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = scanner.nextInt();
}
}
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (a == 1) {
matrix = rebuild(matrix, b, c);
} else if (a == 2) {
transpose();
} else {
if (isTransed) {
System.out.println(matrix[c][b]);
} else {
System.out.println(matrix[b][c]);
}
}
}
}
// 转置
private static void transpose() {
isTransed = !isTransed;
int temp = n;
n = m;
m = temp;
}
// 重塑
private static int[][] rebuild(int[][] matrix, int p, int q) {
int[][] matrix2 = new int[p][q];
// 下标指针
int pp = 0, qq = 0;
if (isTransed) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[j][i];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
} else {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[i][j];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
}
n = p;
m = q;
isTransed = false; // 重塑后矩阵返回原始状态
return matrix2;
}
}
代码三(过80%)
将重塑也进行了优化,只在输出时判断是否需要重塑,但是还是超时。
推测可能有大量重塑查询交替的判断,而二维数组重塑的时间复杂度为O(n*m),因此再往优化的话必须转为一维数组了。
import java.util.Scanner;
class Main {
static int n, m;
static boolean isTransed = false;
static boolean isRebuild = false;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int t = scanner.nextInt();
// 读入矩阵
int[][] matrix = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = scanner.nextInt();
}
}
int p = 0, q = 0;
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (a == 1) {
isRebuild = true;
p = b;
q = c;
} else if (a == 2) {
isTransed = !isTransed;
int temp = n;
n = m;
m = temp;
} else {
if (isRebuild) {
matrix = rebuild(matrix, p, q);
isRebuild = false;
}
if (isTransed) {
System.out.println(matrix[c][b]);
} else {
System.out.println(matrix[b][c]);
}
}
}
}
// 重塑
private static int[][] rebuild(int[][] matrix, int p, int q) {
int[][] matrix2 = new int[p][q];
// 下标指针
int pp = 0, qq = 0;
if (isTransed) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[j][i];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
} else {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[i][j];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
}
n = p;
m = q;
isTransed = false; // 重塑后矩阵返回原始状态
return matrix2;
}
}
代码四(过80%)
import java.util.Scanner;
class Main {
static int n, m;
static boolean isTransed = false;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int t = scanner.nextInt();
// 读入矩阵
int[] matrix = new int[n * m];
for (int i = 0; i < n * m; i++) {
matrix[i] = scanner.nextInt();
}
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int c = scanner.nextInt();
if (a == 1) {
n = b;
m = c;
} else if (a == 2) {
isTransed = !isTransed;
} else if (a == 3) {
if (isTransed) {
matrix = transpose(matrix);
isTransed = false;
}
System.out.println(matrix[b * m + c]);
}
}
}
// 转置
private static int[] transpose(int[] matrix) {
int[] matrix2 = new int[m * n];
int temp = n;
n = m;
m = temp;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[i * m + j] = matrix[j * n + i];
}
}
return matrix2;
}
}
时间限制是1s,还是差了一点点,已经优化的很极限了,按理说不应该,然后转成c++代码试了一下。
AC代码(代码四C++版)
#include <iostream>
using namespace std;
int n, m;
bool isTransed = false;
// 转置
int* transpose(int* matrix) {
int* matrix2 = new int[m * n];
int temp = n;
n = m;
m = temp;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[i * m + j] = matrix[j * n + i];
}
}
delete[] matrix; // 释放旧的矩阵内存
return matrix2;
}
int main() {
cin >> n >> m;
int t;
cin >> t;
// 读入矩阵
int* matrix = new int[n * m];
for (int i = 0; i < n * m; i++) {
cin >> matrix[i];
}
while (t-- > 0) {
int a, b, c;
cin >> a >> b >> c;
if (a == 1) {
n = b;
m = c;
}
else if (a == 2) {
isTransed = !isTransed;
}
else if (a == 3) {
if (isTransed) {
matrix = transpose(matrix);
isTransed = false;
}
cout << matrix[b * m + c] << endl;
}
}
delete[] matrix; // 释放动态分配的内存
return 0;
}
沉默了。。。。。。
看了下CSP官方的说明,结果竟然发现时间限制是一样的????
看得出来主办方是C++工程师。。。
AC代码(代码一C++版)
#include <iostream>
using namespace std;
int n, m;
int** transpose(int** matrix);
int** rebuild(int** matrix, int p, int q);
int main() {
cin >> n >> m;
int t;
cin >> t;
// 读入矩阵
int** matrix = new int*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new int[m];
for (int j = 0; j < m; j++) {
cin >> matrix[i][j];
}
}
while (t-- > 0) {
int a, b, c;
cin >> a >> b >> c;
if (a == 1) {
matrix = rebuild(matrix, b, c);
} else if (a == 2) {
matrix = transpose(matrix);
} else {
cout << matrix[b][c] << endl;
}
}
// 释放内存
for (int i = 0; i < n; i++) {
delete[] matrix[i];
}
delete[] matrix;
return 0;
}
// 转置
int** transpose(int** matrix) {
int** matrix2 = new int*[m];
for (int i = 0; i < m; i++) {
matrix2[i] = new int[n];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[j][i] = matrix[i][j];
}
}
for (int i = 0; i < n; i++) {
delete[] matrix[i];
}
delete[] matrix;
int temp = n;
n = m;
m = temp;
return matrix2;
}
// 重塑
int** rebuild(int** matrix, int p, int q) {
int** matrix2 = new int*[p];
for (int i = 0; i < p; i++) {
matrix2[i] = new int[q];
}
int pp = 0, qq = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix2[pp][qq] = matrix[i][j];
qq++;
if (qq == q) {
qq = 0;
pp++;
}
}
}
for (int i = 0; i < n; i++) {
delete[] matrix[i];
}
delete[] matrix;
n = p;
m = q;
return matrix2;
}
又试了一下最开始的未优化版本,发现用c++也能过,只能说对java选手非常不友好。。。
(by 归忆)