每个案例第一行三个正整数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
#include <iostream>
using namespace std;
int main()
{
int N,M,K;
while(cin>>N>>M>>K){
int matrix[N][M];
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
cin>>matrix[i][j];
int minS=123123123;
for(int i=0;i<N;i++){
int b[M]={0};
for(int j=i;j<N;j++){
int linecount=j-i+1;
for(int k=0;k<M;k++) b[k]+=matrix[j][k];
int rowcount=0,k=0,temp=0;
for(;k<M;k++){
temp+=b[k]; //temp为 从i~j行,rowcount~k列的总值
if(temp>=K){ //该子矩阵达到要求
if(minS>linecount*(k-rowcount+1)) //更新最小面积
minS=linecount*(k-rowcount+1);
if(minS==1){ //已达到所能达到最小值,剪枝
printf("1\n");
return 0;
}
k=rowcount++; //从下一列开始从新计算
temp=0;
}
}
}
}
if(minS==123123123) printf("-1\n");
else printf("%d\n",minS);
}
return 0;
}
#include<iostream>
(720)#include<algorithm>
using namespace std;
int m,n,k;
int sumg[100][100] = { 0 }; //二维树状数组 注意树状数组下标从1开始
int sumr[100][100] = { 0 }; //子矩阵1,1到x,y的和,下标从1开始。下标为0的一律结果是0
int lowbit(int x) {
return x & (-x);
}
void update(int a,int b,int c) { //更新二维树状数组
for (int i = a; i <= m; i += lowbit(i))
for (int j = b; j <= n; j += lowbit(j))
sumg[i][j] += c;
}
int getsum(int a, int b) { //通过树状数组求子矩阵 1,1到x,y的和。
int sum = 0;
for (int i = a; i >0; i -= lowbit(i))
for (int j = b; j >0; j -= lowbit(j))
sum+=sumg[i][j];
return sum;
}
bool find(int a, int b) { //返回是否能找到一个高为a,长为b的矩阵,和满足>=K 。因为用已经计算好的数组sumr来算的,复杂度为O(m*n),常数项应该比较低
if (a > m)a = m;
if (b > n)b = n;
for (int i = 1; i <= m - a+1; i++) {
for (int j = 1; j <= n - b+1; j++) {
int tempsum = 0;
tempsum = sumr[i+a-1][j+b-1] - sumr[i+a-1][j-1]- sumr[i -1][ j + b - 1]+sumr[i-1][j-1];
if (tempsum >=k)return 1;
}
}
return 0;
}
int main() {
int sum;
cin >> m >> n >> k;
for (int i = 1; i < m+1; i++){ //这个for整个复杂度 m*n*log(n)*log(m)
sum = 0;
for (int j = 1; j < n+1; j++) {
int n; cin >> n;
if (n >= k) { cout << 1; return 0; } //单个元素就比k大了,直接返回
update(i, j, n); //更新二维树状数组
}
}
for (int i = 1; i <= m; i++) { //这个for整个复杂度也是 m*n*log(n)*log(m)
for (int j = 1; j <= n; j++)
sumr[i][j] = getsum(i, j);
}
int maxmn = max(m, n);
int face=-1;
int min=0x3f3f3f3f;
for (int i = 1; i <= maxmn; i++) { //这个for整个复杂度是i,j的m*n再乘以find的m*n复杂度,但是find的m*n常数项很低,故可以不超时。114ms
for (int j = 1; j <= maxmn;j++)
if (find(i, j) || find(j, 1)) {
int temp = i * j;
if (temp < min) { min = temp; face = temp; }
break;
}
}
cout<< face;
return 0;
} #include <bits/stdc++.h>
using namespace std;
int n,m,k,a[110][110],ans,sum,minnum=1<<30;
int GetMin(int tmp_array[]) {
ans=1<<30;
for(int i =0; i<n; i++) {
sum=0;
for(int j=i; j<n; j++) {
sum+=tmp_array[j];
if(sum>=k) {
if(ans>j-i+1) {
ans=j-i+1;
// cout<<ans<<" "<<sum<<" "<<j<<" "<<i<<endl;
break;
}
}
}
}
return ans;
}
int main() {
//freopen("1.txt","r",stdin);
cin>>n>>m>>k;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++) cin>>a[i][j];
int tmp_array[110];
// for(int i=0; i<n; i++)
// for(int j=0; j<m; j++) cout<<a[i][j]<<endl;
for(int i=0; i<n; i++) {
memset(tmp_array,0,sizeof(tmp_array));
for(int j=i; j<n; j++) {
for(int t=0; t<m; t++) {
tmp_array[t]+=a[j][t];
}
// for(int z=0; z<n; z++) cout<<tmp_array[z]<<" ";
// cout<<endl;
int len=GetMin(tmp_array);
if(len==1<<30) continue;
// cout<<minnum<<" "<<j<<" "<<i<<" "<<len<<endl;
minnum=min(minnum,len*(j-i+1));
}
}
cout<<minnum<<endl;
return 0;
}
//参考博客https://blog.csdn.net/Jaster_wisdom/article/details/52153685
#include <iostream>
#define N 101
#define M 101
using namespace std;
int Mat[N][M];
int temp[N][M];
int main()
{
int n,m,k;
while(cin>>n>>m>>k){
int ans=123123123;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>Mat[i][j];
if(i==0){
temp[i][j]=Mat[i][j];
}
else{
temp[i][j]=0;
}
}
}
for(int i=1;i<n;i++)
for(int j=0;j<m;j++){
temp[i][j]=temp[i-1][j]+Mat[i][j];//将矩阵的每行的累加和用辅助矩阵temp进行存储
}
int tmp[m];
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
for(int k=0;k<m;k++){
if(i==0)
tmp[k]=temp[j][k];
else
tmp[k]=temp[j][k]-temp[i-1][k];
}
/*
求解一维数组中,和大于等于k的最短连续子序列的长度.
采用两个指针,一个指向当前处理的子序列的首部一个指向尾部。
①如果当前序列的和小于k,end++
②如果当前序列的和大于k,start++并减去首部的值
记录求解过程中出现的最短序列的长度
*/
int sum=0;
int start=0,end=0;
while(end<m){
sum+=tmp[end];
while(sum>=k){
ans=min(ans,(end-start+1)*(j-i+1));//注意此处需要计算面积
sum-=tmp[start++];
}
end++;
}
}
}
ans==123123123?cout<<-1<<endl:cout<<ans<<endl;//不存在输出-1
}
return 0;
}
/*
4 4 100
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
*/
/*最小面积子矩阵——元素和不小于k的面积的最小矩阵 思路:早上做了最大子矩阵这道题,学到压缩矩阵的方法(还是看保洁妹大佬的代码) 下午就尝试一下这个方法,真的是……不知道说些什么好啊,我是定义一个结构体,因为在想 那个行数的面积s的时候不可能每一个压缩矩阵都要共用一个s,所以就定义一个结构体保存每个压缩的 s#include<stdio.h>如图 之后找最大连续子矩阵就 这部分代码 int sum=0; int s=0; for(j=0;j<m;j++){ if(sum<k){ sum+=buf[j].value; s+=buf[j].s; } } 说出来你们可能不信,我提交好几次才成功了,因为 if(sum>=k){ if(s<min_s){ min_s=s; } } 这部分代码,真的坑啊如果遍历完所有的压缩项依然小于k,那么最小的还是INF,如果不做判断,就会 出现INF变成某个数(因为累加的时候s+=buf[j].s),这里真的要注意啊 */
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;
inline int rd() {
int x = 0;
char c = getchar();
bool f = false;
while (!isdigit(c)) {
if (c == '-') f = true;
c = getchar();
}
while (isdigit(c)) {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f ? -x : x;
}
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }
/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1; y = 0; return a;
}
ans = exgcd(b, a%b, x, y);
ll t = x; x = y; y = t - a / b * y;
return ans;
}
*/
int n, m, K;
int a[200][200];
bool fg;
int pre[maxn];
int dp[maxn];
int minn = inf;
void sol() {
for (int i = 1; i <= n; i++) {
ms(dp);
for (int j = i; j <= n; j++) {
ms(pre);
for (int k = 1; k <= m; k++)
dp[k] += a[j][k];
for (int k = 1; k <= m; k++)pre[k] = pre[k - 1] + dp[k];
int l = 1, r = 1;
while (1) {
if (r > m)break;
while (pre[r] - pre[l - 1] < K&&r <= m)r++;
if (pre[r] - pre[l - 1] >= K&&r<=m) {
minn = min(minn, (j - i + 1)*(r - l + 1));
fg = 1;
}
while (pre[r] - pre[l - 1] >= K && l <= r) {
minn = min(minn, (r - l + 1)*(j - i + 1));
l++;
fg = 1;
}
}
}
}
}
int main()
{
//ios::sync_with_stdio(0);
rdint(n); rdint(m); rdint(K);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)rdint(a[i][j]);
}
sol();
if (fg == 0)cout << -1 << endl;
else {
cout << minn << endl;
}
return 0;
}
#include <stdio.h>
#include <limits.h>
#define N 101
#define M 101
int martix[N][M];//输入的矩阵
int sum[M];//相邻的几行合并而成的一维数组
int m, n, k;
int Shortest(int sum[M])
{//求一维数组里面和不小于k的最短连续序列长度
int from=0, to=0;
int len=INT_MAX;
int x=0;//from到to的序列和
while(to<m)
{
while(x<k&&to<m)//序列和小于k那终点后移
{
x+=sum[to];
to++;
}
while(x>=k&&from<to-1)//序列和不小于k那起点后移
{
if(to-from<len) len=to-from;//这是更短的序列,记下来
x-=sum[from];
from++;
}
if(from+1==to) return 1;//追尾了
}
return len;
}
int main()
{
while(scanf("%d%d%d", &n, &m, &k)!=EOF)
{
for(int i=0; i<n; i++)//输入
{
for(int j=0; j<m; j++)
{
scanf("%d", &martix[i][j]);
}
}
int area=INT_MAX;//满足条件的最小面积,先假设是无穷大
for(int i=0; i<n; i++)//从i行开始合并
{
for(int j=0; j<m; j++) sum[j]=0;//清空sum数组
for(int k=i; k<n; k++)//合并从i行到k行
{
for(int j=0; j<m; j++) sum[j]+=martix[k][j];
int len=Shortest(sum);
if(len!=INT_MAX)
{//如果面积比已有的最小面积还小,那就修改最小面积
if(len*(k-i+1)<area) area=len*(k-i+1);
}
}
}
if(area==INT_MAX) printf("-1\n");
else printf("%d\n", area);
}
return 0;
} // 类似于求最大子矩阵和,O(n*m*m)#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; const int AX = 1e2 + 66 ; int a[AX][AX]; int main() { int n , m , K , x ; scanf("%d%d%d",&n,&m,&K); memset( a , 0 , sizeof(a) ); for( int i = 1 ; i <= n ; i++ ) { for( int j = 1 ; j <= m ; j++ ) { scanf("%d",&a[i][j]); a[i][j] += a[i-1][j] ; } } int res = INF ; for( int i = 1 ; i <= n ; i++ ) { for( int j = 1 ; j <= m ; j++ ) { int sum = 0 ; int area = 0 ; for( int k = 1 ; k <= m ; k++ ) { int tmp = a[j][k] - a[i-1][k] ; if( ( sum < K && tmp <= 0 ) || ( sum >= K && tmp >= 0 ) ) { if( area ) k-- ; sum = 0 ; area = 0 ; } else { sum += tmp ; area += j - i + 1 ; if( sum >= K ) { res = min( res , area ) ; sum = 0 ; area = 0 ; } } } } } printf("%d\n",(res<INF?res:-1)); return 0 ; }
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m,K;
scanf("%d%d%d",&n,&m,&K);
int matric[n+1][m+1];
memset(matric, 0 ,sizeof(matric));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%d",&matric[i][j]);
matric[i][j] += matric[i-1][j];
}
}
int res = INT_MAX;
for(int i = 1; i <= n; i++){
for(int j = i; j <= n; j++){
int tmp = INT_MIN;
int index;
int area = 0;
int dp[m+1];
dp[0] = 0;
for(int k = 1; k <= m; k++){
dp[k] = matric[j][k] - matric[i][k];
if(dp[k]>tmp){
tmp = dp[k];
index = k;
}
}
if(tmp >= K){
area = j - i;
res = min(res, area);
}
else{
for(int k = 1; k <= m; k++){
dp[k] = max( dp[k-1] + dp[k], dp[k]);
if(dp[k] >= K){
area = (j - i)*k;
res = min(res, area);
break;
}
}
}
}
}
printf("%d\n",(res<INT_MAX? res : -1));
return 0;
} #include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 110;
int arr[MAXN][MAXN] = {0};
int brr[MAXN][MAXN];
int main() {
int n, m, k;
while (cin >> n >> m >> k) {
memset(arr, 0, sizeof arr);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> brr[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
arr[i][j] = arr[i][j - 1] + arr[i - 1][j] + brr[i][j] - arr[i - 1][j - 1];
}
}
bool isOk = false;
for (int i = 1; i <= n; i++) { // 宽
for (int j = 1; j <= m; j++) { // 长
for (int o = i; o <= n; o++) {
for (int p = j; p <= m; p++) {
if (arr[o][p] - arr[o - i][p] - arr[o][p - j] + arr[o - i][p - j] >= k ) {
isOk = true;
cout << i *j << endl;
break;
}
}
if (isOk) {
break;
}
}
if (isOk) {
break;
}
}
if (isOk) {
break;
}
}
if (!isOk) {
cout << -1 << endl;
}
}
return 0;
} #include <ios>
#include<iostream>
using namespace std;
int m, n, k;
int main(){
cin >> m >> n >> k;
int matrix[m+1][n+1];
for(int i=0; i<m; ++i){
for(int j=0; j<n; ++j){
cin >> matrix[i+1][j+1];
if(matrix[i+1][j+1]>=k){
cout << 1;
return 0;
}
}
}
for(int i=0; i<=m; ++i) matrix[i][0]=0;
for(int j=0; j<=n; ++j) matrix[0][j]=0;
// 添加第 0 行 0 列后,求和步骤可以和输入合并
for(int i=1; i<=m; ++i){
for(int j=1; j<=n; ++j){
matrix[i][j] += (matrix[i-1][j]+matrix[i][j-1]-matrix[i-1][j-1]);
}
}
if(matrix[m][n]<k){
cout << -1;
return 0;
}
// int l=1, w=1;
int min_s=100001, loop_s=2;
while(loop_s<=m*n){
for(int l=2; l<=loop_s && l<=m; ++l){
if(loop_s % l !=0 || loop_s/l>n) continue;
int w=loop_s/l;
for(int i=1; i+l-1<=m; ++i){
for(int j=1; j+w-1<=n; ++j){
int s=matrix[i+l-1][j+w-1] - matrix[i-1][j+w-1] - matrix[i+l-1][j-1] + matrix[i-1][j-1];
if(s>=k){
cout << loop_s;
return 0;
}
}
}
}
++loop_s;
}
return 0;
} #include<iostream>
#include<vector>
#include<climits>
using namespace std;
int main(){
int n, m,k;
cin >> n >> m >> k;
vector<vector<int>> matrix(n, vector<int>(m, 0));
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++)
cin >> matrix[i][j];
int result = INT_MAX;
for(int i = 0;i < n;i++){
vector<int> every(m);
for(int j = i;j < n;j++){ //i,j遍历行区间
for(int k = 0;k < m;k++)//计算每列行区间元素之和
every[k] += matrix[j][k];
//----------------------以下是最小子数组的解法
int p = 0, sum = 0, result_per_loop = INT_MAX;
for(int q = 0;q < m;q++){
sum += every[q];
while(sum >= k){
int sublength = q - p + 1;
result_per_loop = result_per_loop > sublength ? sublength : result_per_loop;
sum -= every[p++];
}
}
//------------------------
//不断比较获得最终结果
if(result_per_loop != INT_MAX){
int area = (j - i + 1) * result_per_loop;
result = result > area ? area : result;
}
}
}
cout << (result == INT_MAX ? -1 : result) << endl;
} #include<bits/stdc++.h>
using namespace std;
const int maxn = 101;
int n, m, k, matrix[maxn][maxn];
void init(){
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin>>matrix[i][j];
}
}
}
void work(){
int area = INT32_MAX;
for(int i = 0; i < n; i++){
vector<int> s(m, 0);
for(int j = i; j < n; j++){
for(int a = 0; a < m; a++){
s[a] += matrix[j][a];
}
// 此时已经得到了第 i 行与第 j 行之间每一列的和 s[k]
// 可以用双指针或者说是滑动窗口来得到最小的矩形面积
int sum = s[0];
int low = 0, high = 1; // 左闭右开
while(high < m){
if(sum >= k){
area = min(area, (high - low) * (j - i + 1));
sum -= s[low];
low++;
}else{
sum += s[high];
high++;
}
}
}
}
if(area == INT32_MAX) area = -1;
cout<<area<<endl;
}
int main(){
while(cin>>n>>m>>k){
init();
work();
}
} 前缀和解法,理解简单,方法粗暴
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
using namespace std;
const int MAXN = 103;
int A[MAXN][MAXN]={0};
int minnum = MAXN*MAXN;
int n,m,k;
void judge(int a,int b){
for(int i=a;i<=n;i++){
for(int j=b;j<=m;j++){
int temp = A[i][j]-A[i][b-1]-A[a-1][j]+A[a-1][b-1];
if(temp>=k){
int numbers = (i-a+1)*(j-b+1);
minnum = min(minnum,numbers);
}
}
}
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int temp;
cin>>temp;
A[i][j] = A[i][j-1]+A[i-1][j]-A[i-1][j-1]+temp;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
judge(i, j);
}
}
if(minnum==MAXN*MAXN){
minnum = -1;
}
cout<<minnum<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,K;//n为行数 m为列数
int ma[100][100];//matrix
int me[100];//merge
int mArea=INT_MAX;//最小面积
int main(){
while(cin>>n>>m>>K){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>ma[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){//从第i行到第j行的子矩阵
memset(me,0,sizeof(me));
for(int k=0;k<m;k++){//从首列到最后一列依次merge
for(int l=i;l<=j;l++){//每列的第i行到第j行依次merge
me[k]+=ma[l][k];
}
}
//至此 从第i行到第j行的merge结束
//接下来要研究merge的连续子序列了
//其中 j-i+1 为子矩阵的行数
for(int k=0;k<m;k++){
//从merge[k]出发的子序列
//l-k+1 为子矩阵列数
int sum=0;
for(int l=k;l<m&&(j-i+1)*(l-k+1)<=mArea;l++){
sum+=me[l];
if(sum>=K){//当前子序列超过K了就别再往后看了
mArea=(j-i+1)*(l-k+1);
break;
}
}
}
}
}
if(mArea==INT_MAX)
cout<<"-1"<<endl;
else
cout<<mArea<<endl;
}
} #include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
int n,m,x;
while(cin>>n>>m>>x) {
int h[110][110];
int b[110];
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
cin>>h[i][j];
}
}
int dp[110][110];
for(int i=0; i<m; i++)
dp[0][i]=h[0][i];
for(int i=1; i<n; i++) {
for(int j=0; j<m; j++) {
dp[i][j]=dp[i-1][j]+h[i][j];
}
}
int minx=99999999;
for(int i=0; i<n; i++) {
for(int j=i; j<n; j++) {
for(int o1=0; o1<m; o1++) {
int num=0;
for(int k=o1; k<m; k++) {
if(i==0)
b[k]=dp[j][k];
else
b[k]=dp[j][k]-dp[i-1][k];
num+=b[k];
if(num>x){
int sum=(j-i+1)*(k-o1+1);
if(sum<minx)
minx=sum;
}
}
}
}
}
cout<<minx<<endl;
}
return 0;
} #include <iostream>
#include <string>
#include <vector>
#include <limits.h>
int MinArea(std::vector<std::vector<int>>& matrix, int n, int m, int k){
std::vector<std::vector<int>> tmp;
for (int i = 0; i < n; i++){
tmp.push_back(std::vector<int>(m, 0));
}
int min_area = INT_MAX;
for (int rows = 1; rows <= n; rows++){
for (int i = n-1; i-rows+1 >= 0; i--){
for (int j = 0; j < m; j++){
tmp[i][j] = tmp[i][j] + matrix[i-rows+1][j];
}
int left = 0;
int right = 0;
int sum = 0;
while(left < m && right < m+1){
if (sum < k){
sum = sum + tmp[i][right];
right++;
}else{
if ((right-left)*rows < min_area){
min_area = (right-left)*rows;
}
sum = sum - tmp[i][left];
left++;
}
}
}
}
return min_area;
}
int main(){
std::string N, M, K;
std::string V;
while(std::cin >> N >> M >> K){
int n = std::stoi(N);
int m = std::stoi(M);
int k = std::stoi(K);
std::vector<std::vector<int>> matrix;
for (int i = 0; i < n; i++){
std::vector<int> row;
for (int j = 0; j < m; j++){
std::cin >> V;
row.push_back(std::stoi(V));
}
matrix.push_back(row);
}
int min_area = MinArea(matrix, n, m, k);
std::cout << min_area << std::endl;
}
return 0;
}