1)输入部分
对于输入部分,我定义的输入格式是这样的
前两行为列数和行数
如果文件无法打开,或者输入文件格式不对,均会提示出错并退出
2)二维数组的最大矩形子数组
首先,我使用最最简单的暴力算法,直接用四个for循环实现,这个算法虽然时间复杂度达到O(M^2*N^2),但可以用于检测优化算法的正确性。
int maxNum1(int m,int n){
int pre[][] = {};
int sum = ,max = ;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
pre[i][j]=pre[i-][j]+pre[i][j-]-pre[i-][j-]+matrix[i][j]; for(int i=; i<=m; i++)
for(int j=;j<=n;j++)
for(int k=i; k<=m; k++)
for(int l=j; l<=n; l++){
sum = pre[k][l] - pre[k][j-] - pre[i-][l] + pre[i-][j-];
if(sum > max)
max = sum;
}
return max;
}
matrix是存放输入的二维数组,从[1][1]开始
pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+matrix[i][j];
是将pre[i][j]存放从matrix[1][1]到matrix[i][j]这个的矩形数组和
故在后面可以用
sum = pre[k][l] - pre[k][j-1] - pre[i-1][l] + pre[i-1][j-1];
一维的情况,上次已经给出了O(N)的算法,是否可以在二维也用上呢?
我是将一个维度上使用暴搜,另一个维度上为上次作业给出的O(N)的算法
int maxNum2(int m,int n){
int pre[][] = {};
int sum = ,max = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
pre[i][j] = pre[i][j-] + matrix[i][j]; for(int i=; i<=n; i++)
for(int j=i;j<=n;j++){
for(int k=; k<=m; k++){
if(sum<)
sum=pre[k][j] - pre[k][i-];
else
sum+=pre[k][j] - pre[k][i-];
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax;
}
这次的处理和上一个不一样,由于在一个维度上用了那个O(N)算法,所以pre[i][j]存的是i行 matrix[i][1]到matrix[i][j]的和
这样算法的时间复杂度为O(M*N^2)
其实,还可以优化一点,就是选择使用O(N)算法的维度时选择M,N中大者,则时间复杂度可以降到O(M*N*min(M,N))
3)水平,垂直!
这个改动,我想了想,水平的话就是水平方向在放一个同样的数组,然后继续用2)中算法
垂直也一样的
2 | -1 | 3 |
-1 | 1 | -2 |
变为
2 | -1 | 3 | 2 | -1 | 3 |
-1 | 1 | -2 | -1 | 1 | -2 |
这样的话,就容易了
int maxNum4(int m, int n){
int pre[][] = {};
int sum = ,max = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=*n;j++)
pre[i][j] = pre[i][j-] + matrix[i][(j-)%n +]; for(int i=; i<=n; i++)
for(int j=i;j<=i+n-;j++){
for(int k=; k<=m; k++){
if(sum<)
sum=pre[k][j] - pre[k][i-];
else
sum+=pre[k][j] - pre[k][i-];
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax;
}
算法上有些小改动,就是要限制子数组行列不超过原数组
垂直的就不在这写了。
4)轮胎?备胎~
这个我是这样想的,就是将4个原数组拼接一个大数组,然后继续用前面的算法
1 | -1 |
-1 | 2 |
变为
1 | -1 | 1 | -1 |
-1 | 2 | -1 | 2 |
1 | -1 | 1 | -1 |
-1 | 2 | -1 | 2 |
在实现上和上面的水平代码大同小异。
5)连通!真的想不出来了
首先想到贪心,二维贪心好像不可行
接着想用图论,把矩阵转为一个有向图,求出一条最大连通路径
使用了各种最短路径算法,还是不行
真心难啊。放弃治疗!
附:代码)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> #define FIE "Input string was not in a correct format"
FILE* in;
int matrix[][] = {};
int map[][] = {};
int sxbkM[][] = {-}; void positiveSub(int m, int n, int label );
inline void error(char* s){
printf("Error: ");
printf("%s\n",s);
exit();
}
int maxNum1(int m,int n){
int pre[][] = {};
int sum = ,max = ;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
pre[i][j]=pre[i-][j]+pre[i][j-]-pre[i-][j-]+matrix[i][j]; for(int i=; i<=m; i++)
for(int j=;j<=n;j++)
for(int k=i; k<=m; k++)
for(int l=j; l<=n; l++){
sum = pre[k][l] - pre[k][j-] - pre[i-][l] + pre[i-][j-];
if(sum > max)
max = sum;
}
return max;
}
int maxNum2(int m,int n){
int pre[][] = {};
int sum = ,max = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
pre[i][j] = pre[i][j-] + matrix[i][j]; for(int i=; i<=n; i++)
for(int j=i;j<=n;j++){
for(int k=; k<=m; k++){
if(sum<)
sum=pre[k][j] - pre[k][i-];
else
sum+=pre[k][j] - pre[k][i-];
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax;
}
//水平
int maxNum4(int m, int n){
int pre[][] = {};
int sum = ,max = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=*n;j++)
pre[i][j] = pre[i][j-] + matrix[i][(j-)%n +]; for(int i=; i<=n; i++)
for(int j=i;j<=i+n-;j++){
for(int k=; k<=m; k++){
if(sum<)
sum=pre[k][j] - pre[k][i-];
else
sum+=pre[k][j] - pre[k][i-];
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax;
} //竖直环
int maxNum5(int m,int n){
int pre[][] = {};
int sum = ,max = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
pre[i][j] = pre[i][j-] + matrix[i][j]; int x=;
for(int i=; i<=n; i++)
for(int j=i;j<=n;j++){
for(int k=; k <= m*; k++){
if(sum< || x >m){
x=;
sum=pre[(k-)%m + ][j] - pre[(k-)%m + ][i-];
}
else{
x++;
sum+=pre[(k-)%m + ][j] - pre[(k-)%m + ][i-];
}
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax;
}
//备胎
int maxNum6(int m, int n){
int pre[][] = {};
int sum = ;
int columnsMax = ;
for(int i=;i<=m;i++)
for(int j=;j<=*n;j++)
pre[i][j] = pre[i][j-] + matrix[i][(j-)%n +]; int x=;
for(int i=; i<=n; i++)
for(int j=i;j<=i+n-;j++){
for(int k=; k <= m*; k++){
if(sum< || x >m){
x=;
sum=pre[(k-)%m + ][j] - pre[(k-)%m + ][i-];
}
else{
x++;
sum+=pre[(k-)%m + ][j] - pre[(k-)%m + ][i-];
}
if(columnsMax < sum)
columnsMax = sum;
}
sum = ;
} return columnsMax; } int getNum(){
char num[],input;
int i=,n;
input = fgetc(in);
while(!isdigit(input) && input != '-' ){
if(input != ' ' && input != '\n' &&
input != NULL && input != ',' &&
input != '\0')
error(FIE);
input = fgetc(in);
} do{
num[i++] = input;
input = fgetc(in);
}while(isdigit(input)); num[i] = '\0';
n = atoi(num); return n;
}
void initialize(int m,int n){
for(int i=; i<; i++)
for(int j=; j<; j++)
sxbkM[i][j] = -;
for(int i=; i<=m; i++){
for(int j=; j<=n; j++){
matrix[i][j] = getNum();
}
}
}
int maxNum3(int m, int n){
return ;
}
void positiveSub(int i, int j, int label ){
map[i][j] = label;
if(matrix[i][j+] >= && map[i][j+] ==)
positiveSub(i,j+,label); if(matrix[i+][j] >= && map[i+][j] ==)
positiveSub(i+,j,label); if(matrix[i][j-] >= && map[i][j-] ==)
positiveSub(i,j-,label); if(matrix[i-][j] >= && map[i-][j] ==)
positiveSub(i-,j,label);
} int main(int argc, char *argv[]){ int m,n;
char input,num[];
if( argc == )
error("Plese run with the file name");
else if(argc == ){
if((in = fopen(argv[], "r")) == NULL)
error("File can not open");
}
else if(argc == ){
if((in = fopen(argv[], "r")) == NULL)
error("File can not open");
}
else if(argc == ){
if((in = fopen(argv[], "r")) == NULL)
error("File can not open");
}
else error("Too many parameters"); m = getNum();
if(fgetc(in)!= '\n')
error(FIE);
n = getNum();
if(fgetc(in)!= '\n')
error(FIE);
initialize(m,n); if( argc == )
std::cout<<std::endl<<"子数组: "<< maxNum2(m,n);
else if( argc == ){
if(strcmp(argv[],"/a") == )
printf("Sorry,I haven't solved the problem.\n");
else if(strcmp(argv[],"/h") == )
std::cout<<std::endl<<"水平环: "<< maxNum4(m,n);
else if(strcmp(argv[],"/v") == )
std::cout<<std::endl<<"竖直环: "<< maxNum5(m,n);
else error("Wrong parameter");
}
else{
if((strcmp(argv[],"/v") == && strcmp(argv[],"/h") == )
||(strcmp(argv[],"/h") == && strcmp(argv[],"/v") == ) )
std::cout<<std::endl<<"备胎环: "<< maxNum6(m,n);
else error("Wrong parameter\n");
}
return ;
}