一、PKU ACM1050——穷举、穷举简化、分治、动态规划
穷举法:
找出所有矩形的值,一个一个比较求出最大值。时间复杂度O(N^4),空间复杂度O(1)。
int func(int **pMatrix,int num)
{
int max = INT_MIN;
int sum = 0;
int maxI = 0;//最大值出现的矩形左上角的列下标
int maxJ = 0;最大值出现的矩形左上角的行下标
int maxII = 0;//最大值出现的矩形右下角的列下标
int maxJJ = 0;//最大值出现的矩形右下角的行下标
int i = 0;//当前矩形左上角的列下标
int j = 0;//当前矩形左上角的行下标
int ii = 0;//当前矩形右下角的列下标
int jj = 0;//当前矩形右下角的行下标
int n = 0;//当前元素列下标
int m = 0;//当前元素行下标
for(i = 0;i < num;i++)
for(j = 0;j < num;j++)
{
cout << "i=" << i << endl;
cout << "j=" << j << endl;
cout << endl;
for(ii = i;ii < num;ii++)
for(jj = j ;jj < num;jj++)
{
cout << "ii=" << ii << endl;
cout << "jj=" << jj << endl;
cout << endl;
for(n = i;n <= ii;n++)
{
for(m = j;m <= jj;m++)
{
sum += pMatrix[n][m];
}
}
cout << "sum=" << sum;
cout << endl;
if(sum > max)
{
max = sum;
maxII = ii;
maxJJ = jj;
maxI = i;
maxJ = j;
cout << "########" << endl;
cout << "sum=" << sum << endl;
cout << "########" << endl;
}
sum = 0;
//system("pause");
}
}
return max;
}
穷举法简化:
举例子,在
9,2,-6,2,
-4,1,-4,1,
-1,8,0,-2
中,求矩形
0,-2,-7,0,
9,2,-6,2
可在
0,-2,-7,
9,2,-6
基础上加上
0,
2
即可计算出来。若函数a(li,lj,ri,rj)表示所求矩形的值,四形参的值分别表示,矩形左上角值的行下标,矩形左上角值的列下标,矩形右下角值的行下标,矩形右下角值的列下标。则a(li,lj,ri,rj+1)= a(li,lj,ri,rj)+ a(0,rj,0,rj)+ a(1,rj,1,rj)+……+ a(ri,rj,ri,rj)。
但是时间复杂度仍是O(N^4),空间复杂度O(1)。
分治法:
将数组从中间切开,分为两半。则该数组的最大矩形和有三种情况:
2) 其与数组右半部分的最大矩形和相同;
3) 其值= a(li,lj,ri,rj),lj<=n/2,rj>=n/2+1。
对前两种情况再次使用“切开”。
而对第三种情况,如下计算——在左右两半数组各计算出所有符合下列情况的矩形和:该矩形一定包含边界上的元素,该矩形行数范围是1~n,列数范围是1~n/2。然后左右数组将对应(左右放到一起可以组成一个矩形的)的矩形和相加,求出当中的最大值,该值即为第三种情况下的最大矩形和。
设计出的递归函数算法如下:
2) 求出数组右半部分最大矩形和;
3) 求出跨越数组左右两部分的最大矩形和;
4) 将以上三值比较,返回最大值。
动态规划法:
网上搜的算法很多是从一维衍生到二维的,以下转载《编程之美》对一维的分析。
方法---动态规划法
当0 = i = j时,元素A[0]本身构成和最大的一段;
当0 = i < j时,和最大的一段以A[0]开始;
当0 < i时,和最大的一段与A[0]没有关系;
假设(A[1], … ,A[n-1])中和最大的一段之和为All[1],并且已经知道(A[1], … ,A[n-1])中包含A[1]的和最大的一段为Start[1],可以看出(A[0], … ,A[n-1])中问题的解All[0]是三种情况最大值max{A[0], A[0] + Start[1] , All[1]}。符合无后效性,用动态规划法求解。
int max(int x, int y)
{
return (x > y) ? x : y;
}
int MaxSum(int *A , int n )
{
Start[n-1] = A[n-1];
All[n-1] = A[n-1];
for(int i = n - 2; i >= 0; i--)
{
Start[i] = max(A[i], A[i]+Start[i+1]);
All[i] = max(Start[i], All[i+1]);
}
return All[0];
}
基本思想是懂的,但是怎么转化到分析这个二维数组呢?倒是有问题,比较笨,暂时MARK下。