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 | -1 | 3 |
-1 | 1 | -2 |
变为
2 | -1 | 3 | 2 | -1 | 3 |
-1 | 1 | -2 | -1 | 1 | -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 |
-1 | 2 |
变为
1 | -1 | 1 | -1 |
-1 | 2 | -1 | 2 |
1 | -1 | 1 | -1 |
-1 | 2 | -1 | 2 |
在实现上和上面的水平代码大同小异。
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 }