列表

详情


NC206587. 数字矩阵

描述

小L老师在黑板上写下一个n行m列只含有数字的矩阵。写完后,小L老师就询问一个问题,
在这个数字矩阵中有多少个包含1的子矩阵。聪明的小明很快就能想出来并给出了答案。于是,
小L老师就对这个子矩阵加了一些限制条件:
1.子矩阵有4个整数x1,y1,x2,y2来定义,(1x1<x2n,1y1<y2m)
2.子矩阵的4个顶角中数字要相同。
3.子矩阵最多包含k个1.
小L老师这次的问题是在这矩阵中满足上面所诉条件的子矩阵的个数。小明一下子得不出答案,聪明的你
能帮助小明解决这个问题嘛

输入描述

第一行一个整数T(1≤T≤100),表示共有T组测试数据。
对于每组测试数据,第一行三个整数n,m,k(2≤n,m≤100,0≤k≤n*m),表示数字矩阵的行数和列数,还有最多包含1的个数。
接下来有n行只含有数字的字符串,每行m个字符

输出描述

输出满足子矩阵限制条件的个数。

示例1

输入:

2
3 3 1
000
101
000
3 2 1
00
01
00

输出:

2
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 755ms, 内存消耗: 480K, 提交时间: 2020-06-08 23:43:13

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define per(i,n,x) for(int i=n;i>=x;i--)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e5+10;
const int inf=1e9;
int T,n,m,K;
char s[110][110];
int a[110],b[110][11];
int main(){
    ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    cin>>T;
    while(T--){
        cin>>n>>m>>K;
        rep(i,1,n) cin>>s[i]+1;
        ll ans=0;
        rep(i,1,n){
            rep(j,1,m) a[j]=0;
            rep(j,i,n){
                rep(k,1,m){
                    if(s[j][k]=='1') a[k]++;
                    rep(p,0,9) b[k][p]=b[k-1][p];
                    if(s[i][k]==s[j][k]) b[k][s[i][k]-'0']++;
                }
                if(j==i) continue;
                int now=0,cnt=0;
                for(int k=1;k<=m;k++){
                    if(now<k){
                        now=k;
                        cnt=0;
                    }
                    while(now<=m&&cnt+a[now]<=K){
                        cnt+=a[now];
                        if(s[i][now]==s[j][now]&&now>k) ans+=b[now-1][s[i][now]-'0']-b[k-1][s[i][now]-'0'];
                        now++;
                    }
                    if(now>k) cnt-=a[k];
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 469ms, 内存消耗: 608K, 提交时间: 2020-06-07 16:10:50

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,m,k,a[N][N],b[N],c[N],z[N][10];
char s[N][N];
int solve()
{
    int ans=0;
    for(int i=1;i<=m;i++)
    {
        b[i]+=b[i-1];
        for(int j=0;j<10;j++)
            z[i][j]=z[i-1][j]+(c[i]==j);
    }
    for(int i=1,j=1;i<=m;i++)
    {
        while(j<=m&&b[j]-b[i-1]<=k) j++;
        assert(j>=i);
        if(j-1>=i&&c[i]!=-1)
        {
            ans+=z[j-1][c[i]]-z[i][c[i]];
        }
    }
    assert(ans>=0);
    return ans;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            a[i][j]=(s[i][j]=='1')+a[i-1][j];
            //assert(s[i][j]=='0'||s[i][j]=='1');
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
        {
            for(int k=1;k<=m;k++)
                b[k]=a[j][k]-a[i-1][k],c[k]=(s[i][k]!=s[j][k])?-1:(s[i][k]-'0');
            ans+=solve();
        }
        printf("%lld\n",ans);
    }
}

上一题