参考博客 https://blog.csdn.net/Sirius_han/article/details/82313029#commentsedit
题意:给定一个n*m的矩阵 和几个障碍点 问存在多少个不包含障碍点的子矩阵
完全暴力代码(不含障碍格子的计数版)
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin>>T;
int Tcase =0;
while(T--)
{
int a,b,c,d,n,m,ko;
scanf("%d%d%d",&n,&m,&ko);
long long ans = 0;
for(int i=1;i<=n;i++)//i(1~n)依次枚举高为h,h-1,h-2,...,1的子矩阵
{
for(int j=1;j<=m;j++)//长度最长是m
{
for(int k=j;k>=1;k--)
{
ans+=i;
}
}
cout<<ans<<endl;
}
printf("Case #%d: %lld\n",++Tcase,ans);
}
return 0;
}
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int a[200000][300],blo[220];
int main()
{
int T;
cin>>T;
int Tcase =0;
while(T--)
{
int b,c,d,n,m,ko;
scanf("%d%d%d",&n,&m,&ko);
long long ans = 0;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
a[i][j] = 0;
blo[j] = 0;
}
}
int k1,k2;
for(int i=1;i<=ko;i++)
{
scanf("%d%d",&k1,&k2);
a[k1][k2] = 1;
}
for(int i=1;i<=n;i++)//i(1~n)依次枚举高为h,h-1,h-2,...,1的子矩阵
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)//看一下第j列(第i行)有没有黑点,有的话记录一下
{
blo[j] = i;
}
}
for(int j=1;j<=m;j++)//长度最长是m
{
long long tmp = i;
for(int k=j;k>=1;k--)
{
tmp = min(tmp,(long long )i-blo[k]);
ans+=tmp;
}
}
// cout<<ans<<endl;
}
printf("Case #%d: %lld\n",++Tcase,ans);
}
return 0;
}
刚学了o(n*m)版本的
参考的剑锋的思路,见他的博客
#include<bits/stdc++.h>
using namespace std;
struct node
{
int p,x;
};
int col[500];
int tu[200010][250];
int main()
{
int n,m,k,p1,p2;
int T;
cin>>T;
int cases =0 ;
while(T--)
{
cases++;
cin>>n>>m>>k;
memset(tu,0,sizeof tu);
for(int i=1; i<=k; i++)
{
cin>>p1>>p2;
tu[p1][p2] = 1;
}
memset(col,0,sizeof col);
long long ans = 0;
int sum[400]= {0};
for(int i =1; i<=n; i++)
{
stack<node>o;
o.push(node{0,n+1});
sum[0] = 0;
for(int j=1; j<=m; j++)
{
if(tu[i][j]==1)col[j] = i;
while(o.top().x<=col[j])
{
o.pop();
}
sum[j] = sum[o.top().p]+(i-col[j])*(j-o.top().p) ;
ans += sum[j];
o.push(node{j,col[j]});
}
//cout<<ans<<endl;
}
cout<<"Case #"<<cases<<": "<<ans<<endl;
}
return 0;
}