#include <stdio.h>
const int size = 110;
int mat[size][size];
int sum[size][size];
int tok[size];
int n, m, k;
bool check(int len)
{
for (int i = 1; i + len - 1 <= m; i ++)
if (tok[i + len - 1] - tok[i - 1] >= k)
return true;
return false;
}
int main()
{
int a;
while (scanf("%d %d %d", &n, &m, &k) != EOF)
{
for (int i = 1; i <= m; i ++)
sum[0][i] = 0;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
{
scanf("%d", &mat[i][j]);
sum[i][j] = sum[i-1][j] + mat[i][j];
}
int ans = -1;
for (int len = 1; len <= n; len ++)
for (int i = 1; i + len - 1 <= n; i ++)
{
tok[0] = 0;
for (int j = 1; j <= m; j ++)
{
tok[j] = sum[i + len - 1][j] - sum[i - 1][j];
tok[j] += tok[j-1];
}
if (tok[m] < k)
continue;
// printf("len = %d, %d!!\n", len, tok[m]);
//枚举len,二分mid
int lf = 1, rt = m + 1;
int mid;
while (lf < rt)
{
mid = (lf + rt) >> 1;
// printf("....(%d, %d)\n", lf, rt);
if (ans != -1 && mid * len > ans)
{
rt = mid;
continue;
}
if (check(mid))
{
if (ans == -1 || ans > mid * len)
ans = mid * len;
rt = mid;
//printf("ans = %d\n", ans);
}
else lf = mid + 1;
}
}
printf("%d\n", ans);
}
return 0;
}
这题没做……
思路是:
1.
DP+二分查找,二维转化为一维求连续子数组最大值
2.两个方向上遍历,计算每个点与左上角的点的和,再遍历计算任意两点间矩阵的部分和
-
题目描述:
-
一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积)
-
输入:
-
每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K
接下来N行,每行M个数,表示矩阵每个元素的值
-
输出:
-
输出最小面积的值。如果出现任意矩阵的和都小于K,直接输出-1。
-
样例输入:
-
4 4 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-
样例输出:
-
1