最大联通子数组
题目:返回一个二维整数数组中最大联通子数组的和
要求: 1. 输入一个二维整形数组,数组里有正数也有负数。 求所有子数组的和的最大值。要求时间复杂度为O(n)。
2.程序要使用的数组放在一个叫 input.txt 的文件中, 文件格式是: 数组的行数, 数组的列数, 每一行的元素, (用逗号分开) 每一个数字都是有符号32位整数,当然,行数和列数都是正整数。
分析:矩阵中的数是随机生成的,可能会有正有负,所以要首先判断二维数组中哪些位置上的数是正数,利用另一个二维数组记录正数的位置,然后判断哪些数是连通的,我的思路是先判断两个数的行数(列数)是否相同,如果相同,再判断列数(行数)是否相邻,如果相邻即证明两个数连通,计算每个连通块的数值的和,然后再连通不同的块,计算其和,最后比较其中的最大值,即为二维整数数组中最大联通子数组的和。
代码:
1 #include<iostream> 2 #define N 100 3 #include<ctime> 4 #include <fstream> 5 using namespace std; 6 7 typedef struct 8 { 9 int d[N]; 10 int a[N][N]; 11 int x; 12 }A; 13 void set(A &array, int x, int y)//x,y分别是行数和列数 14 { 15 array.x = x*y; 16 srand((unsigned)time(NULL)); 17 for (int i = 1; i <= array.x; i++) 18 { 19 array.d[i] = rand() % 10; 20 if (rand() % 2 == 1) 21 array.d[i] = array.d[i] * (-1); 22 }//随机生成数组的数 23 for (int i = 1; i <= array.x; i += y) 24 { 25 for (int j = i; j <= i + y - 2; j++) 26 { 27 array.a[j][j + 1] = 1; 28 array.a[j + 1][j] = 1; 29 } 30 } for (int i = 1 + y; i<array.x; i += y) 31 { 32 for (int j = i; j <= i + x - 1; j++) 33 { 34 array.a[j][j - y] = 1; 35 array.a[j - y][j] = 1; 36 } 37 }//将随机生成的一维数组转换成二维的图的形式 38 } 39 void output(A array) 40 { 41 for (int i = 1; i <= array.x; i++) 42 { 43 cout << array.d[i]; 44 if (array.a[i][i + 1] == 1) 45 cout << " "; 46 else 47 cout << endl; 48 } 49 } 50 void bianli(A &array, int v, int visit[], int&b, int&max, int x) 51 { 52 visit[v] = 1; 53 max += array.d[v]; 54 if (max >= b) 55 b = max; 56 int a = 0, bo = 0; 57 for (int w = 1; w <= array.x; w++) 58 { 59 for (int c = 1; c <= array.x; c++) 60 { 61 if ((visit[w] == 0) && (array.a[c][w] == 1) && (visit[c] == 1)) 62 { 63 a = w; 64 bo = 1; 65 break; 66 } 67 } 68 if (bo == 1) break; 69 } 70 for (int w = 1; w <= array.x; w++) 71 { 72 for (int c = 1; c <= array.x; c++) 73 { 74 if ((visit[w] == 0) && (array.a[c][w] == 1) && (visit[c] == 1)) 75 { 76 if (array.d[a]<array.d[w]) 77 a = w; 78 } 79 } 80 } 81 if (b + array.d[a]<0) 82 { 83 array.a[v][a] = 0; 84 } 85 else 86 bianli(array, a, visit, b, max, x); 87 } 88 //遍历 89 int NoVisit(int visit[], A array) 90 { 91 int k = 0, i; 92 for (i = 1; i <= array.x; i++) 93 { 94 if (visit[i] == 0) 95 { 96 k = i; 97 break; 98 } 99 } return k; 100 }//判断图中没有visit的项 101 int main() 102 { 103 int x, y; 104 ofstream outfile; 105 outfile.open("intput.txt"); 106 if (!outfile) 107 { 108 cerr << "OPEN ERROR!" << endl; 109 exit(0); 110 } 111 cout << "输入数组的行:" << endl; 112 cin >> x; 113 outfile << x << endl; 114 cout << "输入数组的列:" << endl; 115 cin >> y; 116 outfile << y << endl<<endl; 117 A array; 118 set(array, x, y); 119 output(array); 120 int v = 1, b[N] = { 0 }, h = 0; 121 for (int i = 1; i <= array.x; i++) 122 { 123 if (array.d[i]<0) 124 { 125 b[i] = array.d[i]; 126 } 127 else 128 { 129 int visit[N] = { 0 }; 130 int max = 0; 131 bianli(array, i, visit, b[i], max, x); 132 } 133 } 134 int max = b[1]; 135 for (int i = 2; i <= array.x; i++) 136 { 137 if (b[i]>max) max = b[i]; 138 } 139 cout << "最大联通子数组的和是:" << max << endl; 140 outfile << max; 141 }
运行结果截图: