首先对于这道题一维和二维的前缀和都可以解,那我们此处讲一下一维+双指针和普通没有优化的暴力二维,有兴趣的同学可以去尝试用二维前缀+二分法求一下这个题

第一种解法:暴力二维前缀和(只能拿80分)

因为我们用的暴力解,所以想法很简单把每个位置的前缀和都求出来然后一层一层的for循环就可以了,我们打个表看一下,就明白了,用一下题目给的数据


arr[i][j]j=1234
i=11234
25678
39101112


然后我们对每个位置进行二维前缀和的计算;我们看一下代码实现

kul[i][j]=kul[i-1][j]+kul[i][j-1]+arr[i][j]-kul[i-1][j-1];    //arr是输入的数据,ful是我们用来记录二维前缀和的数组

kul[i][j]j=1234
i=11
3610
26142436
315335478

kul数组每个位置记录的都是1~i和1~j所以元素的总和,然后我们直接暴力对每个前缀和做差与题目给的k进行比对小的话结果就加1大的话就直接break;

if(kul[k][p]-kul[i-1][p]-kul[k][j-1]+kul[i-1][j-1]<=val)          //如果可以就一直算下去,不行直接break,也算是个小优化吧
{
    flag++;
}else{
    break;
}

我们看一下完整代码(感兴趣的同学可以优化一下二维前缀可以拿满分,这里就分享一下暴力的做法吧)

#include<stdio.h>
#include<string.h>
#define max 505
int arr[max][max],kul[max][max];
int main()
{
	int n,m,k,val,i,j,p;
	scanf("%d%d%d",&n,&m,&val);
	memset(kul,0,sizeof(kul));
	for(i=1; i<=n; i++)
	{
		for(j=1; j<=m; j++)
		{
			scanf("%d",&arr[i][j]);
			kul[i][j]=kul[i-1][j]+kul[i][j-1]+arr[i][j]-kul[i-1][j-1];
		}
	}
	int flag=0,mi=0;
	for(i=1; i<=n; i++)
	{
		for(j=1; j<=m; j++)
		{
			for(k=i; k<=n; k++)
			{
				for(p=j; p<=m; p++)
				{
					if(kul[k][p]-kul[i-1][p]-kul[k][j-1]+kul[i-1][j-1]<=val)
					{
						flag++;
					}
					else
					{
						break;
					}
				}
			}
		}
	}
	
	printf("%d",flag);
	return 0;
}

第二种解法:一维前缀和加双指针(满分AC)

当然了我们用一维前缀和也是可以做出来的,我们的一维是对于列的一维,看一下表格:

kul[i][j]j=1234
i=11234
2681012
315182124

我们的做法是按行从1开始计算,但我们加的值是按照列来计算的,如果满足题目给的k我们就直接加上就可以了,如果没有满足我们用while循环来进行列的向右遍历,看下源码

#include<stdio.h>
int s[505][505];
int main( )
{
	int n,m,k;
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=m; j++)
		{
			scanf("%d",&s[i][j]);
			s[i][j]+=s[i-1][j];
		}
	}
	long long int res=0;
	for(int i=1; i<=n; i++)
	{
		for(int j=i; j<=n; j++)
		{
			for(int left=1,right=1,sum=0; right<=m; right++)
			{
				sum+=s[j][right]-s[i-1][right];
				while (sum>k)
				{
					sum-=s[j][left]-s[i-1][left];
					left++;
				}
				res+=right-left+1;
			}
		}
	}
	printf("%lld",res);
	return 0;
}


点赞(0)
 

0.0分

54 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 18 条评论

菜鸟求带飞 1年前 回复TA
@菜鸟求带飞 @dotcpp0661505 明白了,谢谢大佬!
又又 1年前 回复TA
@菜鸟求带飞 你画图就可以发现这个矩阵是任意的,可以1x1,可以1x2,2x1,2x2....
又又 1年前 回复TA
@菜鸟求带飞 画个图试一试,这其实就是i-1行和j-1和列围起来里面的那一块矩阵,只不过你减了kul[i-1][p]和kul[k][j-1],kul[i-1[j-]减了两遍,所以加回来
奔跑的吮指原味鸡 1年前 回复TA
@东星耀阳 C++组不养闲人()
奔跑的吮指原味鸡 1年前 回复TA
@楠荀 这四个数相当于x1,y1 x2,y2。建议学一遍前缀和&子矩阵
菜鸟求带飞 1年前 回复TA
@菜鸟求带飞 好的,谢谢大佬
尘客 1年前 回复TA
@菜鸟求带飞 这是二维矩阵区域和的计算公式, 你学一下二维前缀和就会了
菜鸟求带飞 1年前 回复TA
大佬!请问if(kul[k][p]-kul[i-1][p]-kul[k][j-1]+kul[i-1][j-1]<=val)怎么理解??kul[k][p]-kul[i-1][p]-kul[k][j-1]+kul[i-1][j-1]是什么意思?求教!!
dotcpp0643114 1年前 回复TA
@楠荀 我看明白了
Thawne 2年前 回复TA
@Thawne 没事了,想岔劈了,1e8勉勉强强吧