1.引进:
最近打算撸最大子矩阵这类问题,以后所有有关最大最优子矩阵的题目,都会补充道这里面。
嘛,这类问题还是挺有用处的,可以当做打牢基础的一些思维题目或者练习代码能力的题目来看,如有不对之处还请读者指出。哈哈
2.题目参考:
奶牛浴场问题(极大化思想)
参考博客:
这道题最重要的还是要想到每次都计算的极大有效子矩形这一点就可以优化成n^2了,其实自己多想想还是挺好理解的。
我起初这句话半天没看懂~,画图又想了很久之后终于解决了:
1.类似的,需要相应地修改上边界。以此类推,如果这个点是在当前点(确定左边界的点)上方,则修改上边界;如果在下方,则修改下边界;如果处在同一行,则可中止搜索(因为后面的矩形面积都是0了)。 一开始感觉有问题~ ~ ~ 如果以此行为上边界或者写边界不可以吗???
2.对于这种情况,可以用类似的方法从右到左扫描每一个点作为右边界的情况。
想想这两句话还是挺重要的,如果有哪里不懂可以指出来,我会的话可以给大家解答。
上代码:
#include<cstdio>
#include<cstdlib>
#define N 5010
#include<cstring>
int comp(const void*a,const void*b)//用来做比较的函数。
{
return *(int*)a-*(int*)b;
}
int Fcomp(const void*a,const void*b)//用来做比较的函数。
{
return *(int*)b-*(int*)a;
}
int L, W;
int n;
int miny, maxy;
int maxS;
int thisS;
int a[N][2];
int b[N][2];
int temp[N][2];
int main()
{
// freopen("in.txt", "r", stdin);
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
scanf("%d%d", &L, &W);
scanf("%d", &n);
miny = 0;
maxy = W;
maxS = -1;
thisS = 0;
for(int i = 0; i < n; i ++)
{
scanf("%d%d", &a[i][0], &a[i][1]);
b[i][0] = a[i][0];
b[i][1] = a[i][1];
}
a[n][0] = L;
a[n][1] = 0;
a[n + 1][0] = 0;
a[n + 1][1] = 0;
a[n + 2][0] = 0;
a[n + 2][1] = W;
a[n + 3][0] = L;
a[n + 3][1] = W;
b[n][0] = L;
b[n][1] = 0;
b[n + 1][0] = 0;
b[n + 1][1] = 0;
b[n + 2][0] = 0;
b[n + 2][1] = W;
b[n + 3][0] = L;
b[n + 3][1] = W;
qsort(a[0], n + 4, sizeof(a[0]), comp);
// for(int i = 0; i < n + 4; i ++)
// printf("%d %d\n", a[i][0], a[i][1]);
// printf("\n");
for(int i = 0; i < n + 4; i ++)
{
miny = 0;
maxy = W;
for(int j = i + 1; j < n + 4; j ++)
{
thisS = (maxy - miny) * (a[j][0] - a[i][0]);
// printf("+%d ", thisS);
if(thisS > maxS)
maxS = thisS;
if(a[j][1] >= a[i][1] && a[j][1] <= maxy)
maxy = a[j][1];
if(a[j][1] <= a[i][1] && a[j][1] >= miny)
miny = a[j][1];
if(a[j][1] == a[i][1])
break;
}
}
for(int i = 0; i < n + 4; i ++)
{
temp[i][0] = b[i][0];
b[i][0] = b[i][1];
b[i][1] = temp[i][0];
}
qsort(b[0], n + 4, sizeof(b[0]), Fcomp);
for(int i = 0; i < n + 4; i ++)
{
temp[i][0] = b[i][0];
b[i][0] = b[i][1];
b[i][1] = temp[i][0];
}
// for(int i = 0; i <= n; i ++)
// {
// printf("%d %d\n", b[i][0], b[i][1]);
// }
for(int i = 0; i < n + 4; i ++) //整个矩形的左右边界为左右边界
{
thisS = L * (b[i][1] - b[i + 1][1]);
// printf("%d*** ", thisS);
if(thisS > maxS)
maxS = thisS;
}
qsort(a[0], n + 4, sizeof(a[0]), comp);
int ttx = 0;
int tty = W;
for(int i = n + 3; i >= 0; i --)
{
ttx = 0;
tty = W;
for(int j = i - 1; j >= 0; j --)
{
thisS = (tty - ttx) * (a[i][0] - a[j][0]);
// printf("%d^%d^%d\n", tty - ttx, a[i][0] - a[j][0], thisS);
if(thisS > maxS)
maxS = thisS;
if(a[j][1] > a[i][1] && a[j][1] < tty)
tty = a[j][1];
if(a[j][1] < a[i][1] && a[j][1] > ttx)
ttx = a[j][1];
if(a[j][1] == a[i][1])
break;
}
}
printf("%d", maxS);
}



悬线法
待更新。。。