homework-02 二维的,好喝的(二维数组的各种子数组)

 

1)输入部分

对于输入部分,我定义的输入格式是这样的

 

前两行为列数和行数

 

如果文件无法打开,或者输入文件格式不对,均会提示出错并退出

 

2)二维数组的最大矩形子数组

首先,我使用最最简单的暴力算法,直接用四个for循环实现,这个算法虽然时间复杂度达到O(M^2*N^2),但可以用于检测优化算法的正确性。

 

 1 int maxNum1(int m,int n){
 2     int pre[100][100] = {0};
 3     int sum = 0,max = 0;
 4     for(int i=1;i<=m;i++)
 5         for(int j=1;j<=n;j++)
 6             pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+matrix[i][j];
 7 
 8     for(int i=1; i<=m; i++)
 9         for(int j=1;j<=n;j++)
10             for(int k=i; k<=m; k++)
11                 for(int l=j; l<=n; l++){
12                     sum = pre[k][l] - pre[k][j-1] - pre[i-1][l] + pre[i-1][j-1];
13                     if(sum > max)
14                         max = sum;
15                 }
16     return max;
17 }

 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)的算法

 

 1 int maxNum2(int m,int n){
 2     int pre[100][100] = {0};
 3     int sum = 0,max = 0;
 4     int columnsMax = 0;
 5     for(int i=1;i<=m;i++)
 6         for(int j=1;j<=n;j++)
 7             pre[i][j] = pre[i][j-1] + matrix[i][j];
 8 
 9     for(int i=1; i<=n; i++)
10         for(int j=i;j<=n;j++){
11             for(int k=1; k<=m; k++){
12                 if(sum<0)
13                     sum=pre[k][j] - pre[k][i-1];
14                 else
15                     sum+=pre[k][j] - pre[k][i-1];
16                 if(columnsMax < sum)
17                     columnsMax = sum;
18             }
19             sum = 0;
20         }
21 
22     return columnsMax;
23 }

 

 这次的处理和上一个不一样,由于在一个维度上用了那个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-13
-11-2

变为

2-132-13
-11-2-11-2

这样的话,就容易了

 1 int maxNum4(int m, int n){
 2     int pre[100][100] = {0};
 3     int sum = 0,max = 0;
 4     int columnsMax = 0;
 5     for(int i=1;i<=m;i++)
 6         for(int j=1;j<=2*n;j++)
 7             pre[i][j] = pre[i][j-1] + matrix[i][(j-1)%n +1];
 8 
 9     for(int i=1; i<=n; i++)
10         for(int j=i;j<=i+n-1;j++){
11             for(int k=1; k<=m; k++){
12                 if(sum<0)
13                     sum=pre[k][j] - pre[k][i-1];
14                 else
15                     sum+=pre[k][j] - pre[k][i-1];
16                 if(columnsMax < sum)
17                     columnsMax = sum;
18             }
19             sum = 0;
20         }
21 
22     return columnsMax;
23 }

 

算法上有些小改动,就是要限制子数组行列不超过原数组

 

垂直的就不在这写了。

 

4)轮胎?备胎~

这个我是这样想的,就是将4个原数组拼接一个大数组,然后继续用前面的算法

1-1
-12

变为

1-11-1
-12-12
1-11-1
-12-12

在实现上和上面的水平代码大同小异。

 

5)连通!真的想不出来了

首先想到贪心,二维贪心好像不可行

接着想用图论,把矩阵转为一个有向图,求出一条最大连通路径

使用了各种最短路径算法,还是不行

真心难啊。放弃治疗!

 

 

附:代码)

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <ctype.h>
  5 
  6 #define FIE "Input string was not in a correct format"
  7 FILE* in;
  8 int matrix[100][100] = {0};
  9 int map[100][100] = {0};
 10 int sxbkM[1000][1000] = {-1};
 11 
 12 void positiveSub(int m, int n, int label );
 13 inline void error(char* s){
 14     printf("Error: ");
 15     printf("%s\n",s);
 16     exit(0);
 17 }
 18 int maxNum1(int m,int n){
 19     int pre[100][100] = {0};
 20     int sum = 0,max = 0;
 21     for(int i=1;i<=m;i++)
 22         for(int j=1;j<=n;j++)
 23             pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+matrix[i][j];
 24 
 25     for(int i=1; i<=m; i++)
 26         for(int j=1;j<=n;j++)
 27             for(int k=i; k<=m; k++)
 28                 for(int l=j; l<=n; l++){
 29                     sum = pre[k][l] - pre[k][j-1] - pre[i-1][l] + pre[i-1][j-1];
 30                     if(sum > max)
 31                         max = sum;
 32                 }
 33     return max;
 34 }
 35 int maxNum2(int m,int n){
 36     int pre[100][100] = {0};
 37     int sum = 0,max = 0;
 38     int columnsMax = 0;
 39     for(int i=1;i<=m;i++)
 40         for(int j=1;j<=n;j++)
 41             pre[i][j] = pre[i][j-1] + matrix[i][j];
 42 
 43     for(int i=1; i<=n; i++)
 44         for(int j=i;j<=n;j++){
 45             for(int k=1; k<=m; k++){
 46                 if(sum<0)
 47                     sum=pre[k][j] - pre[k][i-1];
 48                 else
 49                     sum+=pre[k][j] - pre[k][i-1];
 50                 if(columnsMax < sum)
 51                     columnsMax = sum;
 52             }
 53             sum = 0;
 54         }
 55 
 56     return columnsMax;
 57 }
 58 //水平
 59 int maxNum4(int m, int n){
 60     int pre[100][100] = {0};
 61     int sum = 0,max = 0;
 62     int columnsMax = 0;
 63     for(int i=1;i<=m;i++)
 64         for(int j=1;j<=2*n;j++)
 65             pre[i][j] = pre[i][j-1] + matrix[i][(j-1)%n +1];
 66 
 67     for(int i=1; i<=n; i++)
 68         for(int j=i;j<=i+n-1;j++){
 69             for(int k=1; k<=m; k++){
 70                 if(sum<0)
 71                     sum=pre[k][j] - pre[k][i-1];
 72                 else
 73                     sum+=pre[k][j] - pre[k][i-1];
 74                 if(columnsMax < sum)
 75                     columnsMax = sum;
 76             }
 77             sum = 0;
 78         }
 79 
 80     return columnsMax;
 81 }
 82 
 83 //竖直环
 84 int maxNum5(int m,int n){
 85     int pre[100][100] = {0};
 86     int sum = 0,max = 0;
 87     int columnsMax = 0;
 88     for(int i=1;i<=m;i++)
 89         for(int j=1;j<=n;j++)
 90             pre[i][j] = pre[i][j-1] + matrix[i][j];
 91 
 92     int x=1;
 93     for(int i=1; i<=n; i++)
 94         for(int j=i;j<=n;j++){
 95             for(int k=1; k <= m*2; k++){
 96                 if(sum<0 || x >m){
 97                     x=1;
 98                     sum=pre[(k-1)%m + 1][j] - pre[(k-1)%m + 1][i-1];
 99                 }
100                 else{
101                     x++;
102                     sum+=pre[(k-1)%m + 1][j] - pre[(k-1)%m + 1][i-1];
103                 }
104                 if(columnsMax < sum)
105                     columnsMax = sum;
106             }
107             sum = 0;
108         }
109 
110     return columnsMax;
111 }
112 //备胎
113 int maxNum6(int m, int n){
114         int pre[100][100] = {0};
115     int sum = 0;
116     int columnsMax = 0;
117     for(int i=1;i<=m;i++)
118         for(int j=1;j<=2*n;j++)
119             pre[i][j] = pre[i][j-1] + matrix[i][(j-1)%n +1];
120 
121     int x=1;
122     for(int i=1; i<=n; i++)
123         for(int j=i;j<=i+n-1;j++){
124             for(int k=1; k <= m*2; k++){
125                 if(sum<0 || x >m){
126                     x=1;
127                     sum=pre[(k-1)%m + 1][j] - pre[(k-1)%m + 1][i-1];
128                 }
129                 else{
130                     x++;
131                     sum+=pre[(k-1)%m + 1][j] - pre[(k-1)%m + 1][i-1];
132                 }
133                 if(columnsMax < sum)
134                     columnsMax = sum;
135             }
136             sum = 0;
137         }
138 
139     return columnsMax;
140     
141 }
142 
143 int getNum(){
144     char num[15],input;
145     int i=0,n;
146     input = fgetc(in);
147     while(!isdigit(input) && input != '-' ){
148         if(input != ' ' && input != '\n' &&
149             input != NULL && input != ',' &&
150             input != '\0')
151             error(FIE);
152         input = fgetc(in);
153     }
154 
155     do{
156         num[i++] = input;
157         input = fgetc(in);
158     }while(isdigit(input));
159 
160     num[i] = '\0';
161     n = atoi(num);
162 
163     return n;
164 }
165 void initialize(int m,int n){
166     for(int i=0; i<1000; i++)
167         for(int j=0; j<1000; j++)
168             sxbkM[i][j] = -1;
169     for(int i=1; i<=m; i++){
170         for(int j=1; j<=n; j++){
171             matrix[i][j] = getNum();
172         }
173     }
174 }
175 int maxNum3(int m, int n){
176     return 0;
177 }
178 void positiveSub(int i, int j, int label ){
179     map[i][j] = label;
180     if(matrix[i][j+1] >= 0 && map[i][j+1] ==0)
181         positiveSub(i,j+1,label);
182 
183     if(matrix[i+1][j] >= 0 && map[i+1][j] ==0)
184         positiveSub(i+1,j,label);
185 
186     if(matrix[i][j-1] >= 0 && map[i][j-1] ==0)
187         positiveSub(i,j-1,label);
188 
189     if(matrix[i-1][j] >= 0 && map[i-1][j] ==0)
190         positiveSub(i-1,j,label);
191 }
192 
193 int main(int argc, char *argv[]){
194 
195     int m,n;
196     char input,num[10];
197     if( argc == 1)
198         error("Plese run with the file name");
199     else if(argc == 2){
200         if((in = fopen(argv[1], "r")) == NULL)
201             error("File can not open");
202     }
203     else if(argc == 3){
204         if((in = fopen(argv[2], "r")) == NULL)
205             error("File can not open");
206     }
207     else if(argc == 4){
208         if((in = fopen(argv[3], "r")) == NULL)
209             error("File can not open");
210     }
211     else error("Too many parameters");
212 
213 
214     m = getNum();
215     if(fgetc(in)!= '\n')
216         error(FIE);
217     n = getNum();
218     if(fgetc(in)!= '\n')
219         error(FIE);
220     initialize(m,n);
221 
222     if( argc == 2)
223         std::cout<<std::endl<<"子数组: "<< maxNum2(m,n);
224     else if( argc == 3){
225         if(strcmp(argv[1],"/a") == 0)
226             printf("Sorry,I haven't solved the problem.\n");
227         else if(strcmp(argv[1],"/h") == 0)
228             std::cout<<std::endl<<"水平环: "<< maxNum4(m,n);
229         else if(strcmp(argv[1],"/v") == 0)
230             std::cout<<std::endl<<"竖直环: "<< maxNum5(m,n);
231         else error("Wrong parameter");
232     }
233     else{
234         if((strcmp(argv[1],"/v") == 0 && strcmp(argv[2],"/h") == 0)
235             ||(strcmp(argv[1],"/h") == 0 && strcmp(argv[2],"/v") == 0) )
236                 std::cout<<std::endl<<"备胎环: "<< maxNum6(m,n);
237         else error("Wrong parameter\n");
238     }
239     return 0;
240 }

 

 

 

转载于:https://www.cnblogs.com/rocbomb/p/3348299.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值