当前位置:   article > 正文

[蓝桥杯 2022 省 B] 统计子矩阵 (前缀和)

[蓝桥杯 2022 省 b] 统计子矩阵

 原题传送门

 该题第一眼给我的感觉就是要使用前缀和解决了

即利用前缀和枚举出所有可能的矩阵情况

这里假设以(1,1)点为起点求可能的所有子矩阵的和,我们定义一个数组temp[i][j]的值为(i,j)这个点到起点(x,y)所连成线的矩阵的权值(即矩阵内每个点的和),这里可以利用动态规划的思想,我们可以很容易想到tmep[i][j]=temp[i-1][j]+temp[i][j-1]-temp[i-1][j-1]

注意要保证数组不要越界

根据上面的思想,我们再枚举每一个点作为起点即可枚举出所有情况

容易知道这样的算法是时间复杂度是n^4的,不过该题的数据范围并不太大,因此还是能通过大部分样例

  1. #include<iostream>
  2. #include<cstring>
  3. #define MAX 505
  4. using namespace std;
  5. int arr[MAX][MAX];
  6. int n,m,k,ans=0;
  7. void fun(int x,int y){//(x,y)为起点
  8. int temp[MAX][MAX];//前缀和数组
  9. for(int i=1;i<=n;i++){
  10. for(int j=1;j<=m;j++){//初始化
  11. temp[i][j]=arr[i][j];
  12. }
  13. }
  14. for(int i=x;i<=n;i++){
  15. for(int j=y;j<=m;j++){//计算前缀和
  16. if(i-1>=x){//小心越界
  17. temp[i][j]+=temp[i-1][j];
  18. }
  19. if(j-1>=y){
  20. temp[i][j]+=temp[i][j-1];
  21. }
  22. if(i-1>=x&&j-1>=y){
  23. temp[i][j]-=temp[i-1][j-1];
  24. }
  25. if(temp[i][j]<=k){//对满足题意的矩阵进行计数
  26. ans++;
  27. }
  28. }
  29. }
  30. // for(int i=1;i<=n;i++){//测试代码
  31. // for(int j=1;j<=m;j++){
  32. // cout<<temp[i][j]<<" ";
  33. // }
  34. // cout<<endl;
  35. // }
  36. }
  37. int main(){
  38. cin>>n>>m>>k;
  39. for(int i=1;i<=n;i++){
  40. for(int j=1;j<=m;j++){
  41. cin>>arr[i][j];
  42. }
  43. }
  44. for(int i=1;i<=n;i++){
  45. for(int j=1;j<=m;j++){//枚举起点
  46. fun(i,j);
  47. }
  48. }
  49. cout<<ans<<endl;
  50. return 0;
  51. }

 上述思路实际上还可以进行优化,不过我并没有想到,感兴趣的读者可以自行搜索

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/374309
推荐阅读
相关标签
  

闽ICP备14008679号