其他分享
首页 > 其他分享> > 【题解】统计子矩阵

【题解】统计子矩阵

作者:互联网

试题 F: 统计子矩阵

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15 分

【问题描述】

给定一个 N × M 的矩阵 A,请你统计有多少个子矩阵 (最小 1 × 1,最大
N × M) 满足子矩阵中所有数的和不超过给定的整数 K?

【输入格式】

第一行包含三个整数 N, M 和 K.
之后 N 行每行包含 M 个整数,代表矩阵 A.

【输出格式】

一个整数代表答案。

【样例输入】

3 4 10
1 2 3 4
5 6 7 8
9 10 11 12

【样例输出】

19

【样例说明】

满足条件的子矩阵一共有 19,包含:
大小为 1 × 1 的有 10 个。
大小为 1 × 2 的有 3 个。
大小为 1 × 3 的有 2 个。
大小为 1 × 4 的有 1 个。
大小为 2 × 1 的有 3 个。

【评测用例规模与约定】

对于 30% 的数据,N, M ≤ 20.
对于 70% 的数据,N, M ≤ 100.
对于 100% 的数据,1 ≤ N, M ≤ 500; 0 ≤ Ai j ≤ 1000; 1 ≤ K ≤ 250000000.


30分思路

朴素做法:5重循环暴力求解


70分思路:

预处理二维前缀和,枚举对角线
时间复杂度:O(nnmm(m+1)(n+1)/4)~O(nnnmmm/4);

70分代码

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,k,a[510][510],s[510][510];
int ans,f[510][510];
int get(int x1,int y1,int x2,int y2)
{
	return s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
}

int main()
{
     cin>>n>>m>>k;
     for(int i=1;i<=n;i++)
     {
     	for(int j=1;j<=m;j++)
     	{
     		cin>>a[i][j];
     		s[i][j]+=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
		}
	 }
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int ii=0;ii<=n-i;ii++)
			{
				for(int jj=0;jj<=m-j;jj++)
				{
					int x1=i,y1=j,x2=i+ii,y2=j+jj;
					if(get(x1,y1,x2,y2)<=k) f[i][j]++;
			
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(f[i][j]) ans+=f[i][j];
		
		}
	}
	cout<<ans;
	return 0;
}

100分思路

二维前缀和+枚举上下界 双指针左右查找

时间复杂度O(nnm)

100分AC代码:

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,k,a[510][510],s[510][510];
long long ans,f[510][510];
#define ll long long
long long get(int x1,int y1,int x2,int y2)
{
    return s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
}

int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
     	{
     	    cin>>a[i][j];
     		s[i][j]+=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
	}
    }
    for(int l=1;l<=m;l++)
    {
        for(int r=l;r<=m;r++)
        {
	    int j=1;
	    for(int i=1;i<=n;i++)
	    {
	        while(j<=i&&1ll*get(j,l,i,r)>k) j++;
	        ans+=(i-j+1);
            }
        }
    }
  /*for(int i=1;i<=n;i++)
    {
	for(int j=1;j<=m;j++)
	{
	    if(f[i][j]) ans+=f[i][j];
	}
    }*/
    cout<<ans;
    return 0;
}

标签:int,题解,矩阵,long,x2,y1,510,y2,统计
来源: https://www.cnblogs.com/watasky/p/16448891.html