Hướng dẫn giải của Đếm ma trận


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của flashmt

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;

int row[222][222],col[222][222],a[222][222],m,n;

int countCells(int x,int xx,int y,int yy)
{
    if (x==xx || y==yy) return xx-x+yy-y+1;
    return 2*(xx-x+yy-y);
}

void updateAns(int val,int cntVal,int &ans,int &cnt)
{
    if (val>ans) ans=val, cnt=cntVal;
    else cnt+=(ans==val)*cntVal;
}

int main()
{
    int test;
    cin >> test;
    while (test--)
    {
        cin >> m >> n;
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
            {
                scanf("%d",a[i]+j);
                row[i][j]=row[i][j-1]+a[i][j];
                col[i][j]=col[i-1][j]+a[i][j];
            }

        int ans=-m*n,cnt=0;

        for (int i=1;i<=m;i++)
            for (int j=0;j<n;j++)
                for (int jj=j+1;jj<=n;jj++)
                    updateAns((row[i][jj]-row[i][j])*2-(jj-j),1,ans,cnt);

        for (int i=0;i<m;i++)
            for (int ii=i+2;ii<=m;ii++)
            {
                int maxCol=-m*n,cntCol=0;
                for (int j=1;j<=n;j++)
                {
                    int cur=(col[ii][j]-col[i][j])*2-(ii-i);
                    int side=(a[ii][j]+a[i+1][j])*2-2;
                    updateAns(cur,1,ans,cnt);
                    updateAns(cur+maxCol,cntCol,ans,cnt);
                    maxCol+=side;
                    if (cur>maxCol) maxCol=cur, cntCol=1;
                    else cntCol+=(cur==maxCol);
                }
            }

        cout << ans << ' ' << cnt << endl;
    }
}

Code mẫu của happyboy99x

#include<iostream>
using namespace std;

const int N = 500, INF = 1e9;
int a[N][N], s[N + 1][N];

void update(int &best, int &cnt, int x, int nway = 1) {
    if(x > best) best = x, cnt = 0;
    if(x == best) cnt += nway;
}

int main() {
    ios::sync_with_stdio(false);
    int numTest; cin >> numTest;
    for(int test = 0; test < numTest; ++test) {
        int m, n; cin >> m >> n;
        for(int i = 0; i < m; ++i) {
            for(int j = 0; j < n; ++j) {
                cin >> a[i][j];
                if(a[i][j] == 0) a[i][j] = -1;
                s[i + 1][j] = s[i][j] + a[i][j];
            }
        }
        int best = -INF, cnt = 0;
        for(int i = 0; i < m; ++i)
            for(int j = 0; j < n; ++j) {
                int sum = a[i][j];
                update(best, cnt, sum);
                for(int k = j + 1; k < n; ++k)
                    update(best, cnt, sum += a[i][k]);
                sum = a[i][j];
                for(int k = i + 1; k < m; ++k)
                    update(best, cnt, sum += a[k][j]);
            }
        for(int top = 0; top < m; ++top)
            for(int bot = top + 1; bot < m; ++bot) {
                int prev = -INF, nway = 1;
                for(int i = 0; i < n; ++i) {
                    int r = s[bot + 1][i] - s[top][i];
                    update(best, cnt, r + prev, nway);
                    if(r > prev + a[top][i] + a[bot][i]) {
                        prev = r, nway = 1;
                    } else {
                        if(r == prev + a[top][i] + a[bot][i]) ++nway;
                        prev = prev + a[top][i] + a[bot][i];
                    }
                }
            }
        cout << best << ' ' << cnt << '\n';
    }
    return 0;
}

Code mẫu của ladpro98

#include <bits/stdc++.h>
const int N = 222;
const int oo = 1000000009;
using namespace std;
int a[N][N], col[N][N], row[N][N], res, m, n, cnt, cmin, minS;

void Upd(int sum) {
    if (res < sum) {
        res = sum;
        cnt = cmin;
    } else
    if (res == sum) cnt += cmin;
}

void Updm(int sum) {
    if (minS > sum) {
        minS = sum;
        cmin = 1;
    } else
    if (minS == sum) cmin++;
}

void Enter() {
    int i, j, s;
        for(i=1; i<=m; i++)
            for(j=1; j<=n; j++) {
                scanf("%d", &a[i][j]);
                if (a[i][j] == 0) a[i][j] = -1;
                col[i][j] = col[i-1][j] + a[i][j];
                row[i][j] = row[i][j-1] + a[i][j];
            }

        for(j=1; j<=n; j++) {
            s = 0; minS = 0; cmin = 1;
            for(i=1; i<=m; i++) {
                s += a[i][j];
                Upd(s - minS);
                Updm(s);
            }
        }
        for(i=1; i<=m; i++) {
            minS = 0; cmin = 1;
            for(j=2; j<=n; j++) {
                s = row[i][j];
                Upd(s - minS);
                Updm(row[i][j-1]) ;
            }
        }
}

int main()
{
    //freopen("MATRIX.in", "r",stdin);
    int i, j, k, t, s;
    scanf("%d\n", &t);
    while (t--) {
        scanf("%d %d\n", &m, &n);
        res = -oo; cnt = 0;
        Enter();
        for(i=1; i<=m; i++)
            for(j=i+1; j<=m; j++) {
                minS = col[i][1] - col[j-1][1];
                cmin = 1;
                for(k=2; k<=n; k++) {
                    s = row[i][k] + row[j][k] + col[j-1][k] - col[i][k];
                    Upd(s - minS);
                    Updm(row[i][k-1] + row[j][k-1] - col[j-1][k] + col[i][k]);
                }
            }
        printf("%d %d\n", res, cnt);
    }
    return 0;
}

Code mẫu của RR

{$R-,Q-}
uses math;
const
  FINP='';
  FOUT='';
  MAXN=201;
var
  f1,f2:text;
  kq,count,test,t,m,n:longint;
  sum,a:array[-1..MAXN,-1..MAXN] of longint;
  nn,sl:array[0..MAXN] of longint;
procedure openF;
begin
  assign(f1,FINP); reset(f1);
  assign(f2,FOUT); rewrite(f2);
end;
procedure closeF;
begin
  close(f1); close(f2);
end;
procedure swap(var a,b:longint);
var
  temp:longint;
begin
  temp:=a; a:=b; b:=temp;
end;
procedure inp; inline;
var
  i,j:longint;
begin
  read(f1,m,n);
  if n=1 then swap(m,n);
  kq:=-1;
  for i:=1 to m do
  for j:=1 to n do
    begin
      read(f1,a[i,j]);
      if a[i,j]=0 then a[i,j]:=-1
      else if a[i,j]=1 then kq:=1;
    end;
end;
procedure ans;
begin
  writeln(f2,kq,' ',count);
end;
procedure solve1;
var
  i:longint;
begin
  for i:=1 to n do
    sum[1,i]:=sum[1,i-1]+a[1,i];
  nn[0]:=sum[1,0]; sl[0]:=1;
  for i:=1 to n do
    if sum[1,i]<nn[i-1] then
      begin
        sl[i]:=1;
        nn[i]:=sum[1,i];
      end
    else if sum[1,i]=nn[i-1] then
      begin
        sl[i]:=sl[i-1]+1;
        nn[i]:=nn[i-1];
      end
    else
      begin
        nn[i]:=nn[i-1];
        sl[i]:=sl[i-1];
      end;
  for i:=1 to n do
    kq:=max(kq,sum[1,i]-nn[i-1]);
  count:=0;
  for i:=1 to n do
    if sum[1,i]-nn[i-1]=kq then inc(count,sl[i-1]);
end;
procedure cal; inline;
var
  i,j:longint;
begin
  for i:=1 to m do
  for j:=1 to n do
    sum[i,j]:=sum[i,j-1]+sum[i-1,j]-sum[i-1,j-1]+a[i,j];
end;
function get(i1,v1,i2,v2:longint):longint; inline;
begin
  if i1>i2 then exit(0);
  if v1>v2 then exit(0);
  get:=sum[i2,v2]-sum[i1-1,v2]-sum[i2,v1-1]+sum[i1-1,v1-1];
end;
procedure solve2;
var
  i1,i2,i,j,gt:longint;
begin
  cal;
  for i1:=1 to m do
  for i2:=i1 to m do
    begin
      nn[0]:=-get(i1+1,1,i2-1,1); sl[0]:=1;
      for j:=1 to n-1 do
        begin
          gt:=get(i1,1,i2,j)-get(i1+1,1,i2-1,j+1);
          if gt<nn[j-1] then
            begin
              nn[j]:=gt;
              sl[j]:=1;
            end
          else if gt=nn[j-1] then
            begin
              nn[j]:=gt;
              sl[j]:=sl[j-1]+1;
            end
          else {gt>nn[j-1]}
            begin
              nn[j]:=nn[j-1];
              sl[j]:=sl[j-1];
            end;
        end;
      for j:=2 to n do
        begin
          gt:=get(i1,1,i2,j);
          gt:=gt-get(i1+1,1,i2-1,j-1);
          gt:=gt-nn[j-2];
          if gt>kq then
            begin
              kq:=gt;
              count:=sl[j-2];
            end
          else if kq=gt then inc(count,sl[j-2]);
        end;
    end;
  for j:=1 to n do
    begin
      fillchar(nn,sizeof(nn),0); fillchar(sl,sizeof(sl),0);
      sl[0]:=1;
      for i:=1 to m do
        if nn[i-1]<sum[i,j]-sum[i,j-1] then
          begin
            nn[i]:=nn[i-1];
            sl[i]:=sl[i-1];
          end
        else if nn[i-1]=sum[i,j]-sum[i,j-1] then
          begin
            nn[i]:=nn[i-1];
            sl[i]:=sl[i-1]+1;
          end
        else
          begin
            nn[i]:=sum[i,j]-sum[i,j-1];
            sl[i]:=1;
          end;
      for i:=1 to m do
        begin
          gt:=sum[i,j]-sum[i,j-1]-nn[i-1];
          if gt>kq then begin kq:=gt; count:=sl[i-1]; end
          else if gt=kq then inc(count,sl[i-1]);
        end;
    end;
end;
begin
  openF;
  read(f1,t);
  for test:=1 to t do
    begin
      inp; count:=0; kq:=-maxlongint;
      if (m=1) and (n=1) then
        begin
          if a[1,1]=1 then writeln(f2,'1 1')
          else writeln(f2,'-1 1');
          continue;
        end;
      if (m>1) then solve2
      else solve1;
      ans;
    end;
  closeF;
end.

Code mẫu của hieult

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <algorithm>

#include <ctime>
#include <deque>
#include <bitset>
#include <cctype>
#include <utility>
#include <cassert>

using namespace std;

typedef long long ll;
typedef double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

#define Rep(i,n) for(int i = 0; i < (n); ++i)
#define Repd(i,n) for(int i = (n)-1; i >= 0; --i)
#define For(i,a,b) for(int i = (a); i <= (b); ++i)
#define Ford(i,a,b) for(int i = (a); i >= (b); --i)
#define Fit(i,v) for(__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++i)
#define Fitd(i,v) for(__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++i)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define sz(a) ((int)(a).size())
#define all(a) (a).begin(), (a).end()
#define ms(a,x) memset(a, x, sizeof(a))

template<class F, class T> T convert(F a, int p = -1) { stringstream ss; if (p >= 0) ss << fixed << setprecision(p); ss << a; T r; ss >> r; return r; }
template<class T> T gcd(T a, T b) { T r; while (b != 0) { r = a % b; a = b; b = r; } return a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> T sqr(T x) { return x * x; }
template<class T> T cube(T x) { return x * x * x; }
template<class T> int getbit(T s, int i) { return (s >> i) & 1; }
template<class T> T onbit(T s, int i) { return s | (T(1) << i); }
template<class T> T offbit(T s, int i) { return s & (~(T(1) << i)); }
template<class T> int cntbit(T s) { return s == 0 ? 0 : cntbit(s >> 1) + (s & 1); }

typedef pair<int, int> II;

const double PI = acos(-1.0);
const double eps = 1e-9;

const int dr[] = {-1, 0, +1, 0};
const int dc[] = {0, +1, 0, -1};

const int inf = (int)1e9 + 5;
const ll linf = (ll)1e16 + 5;
const ll mod = (ll)1e9 + 7;

#define maxn 205

int test, n, m, a[maxn][maxn], r[maxn][maxn], c[maxn][maxn], f[maxn], g[maxn];

int main(){
//    freopen("in.txt", "r", stdin);

    scanf("%d", &test);
    Rep(itest, test){
        scanf("%d %d", &n, &m);
        For(i, 1, n) {
            For(j, 1, m){
                scanf("%d", &a[i][j]);
                if(a[i][j] == 0) a[i][j] = -1;
            }
        }

        ms(c, 0); ms(r, 0);
        For(i, 1, n) For(j, 1, m){
            r[i][j] = r[i][j - 1] + a[i][j];
            c[i][j] = c[i - 1][j] + a[i][j];
        }

        int res = -inf, A;
        ll num = 0, so;

        For(i, 1, n){
            int MIN = 0, so = 1;
            For(j, 1, m){
                A = r[i][j] - MIN;
                if(A == res) num += so;
                if(A > res){
                    num = so;
                    res = A;
                }
                if(r[i][j] == MIN) so++;
                if(r[i][j] < MIN){
                    MIN = r[i][j];
                    so = 1;
                }
            }
        }

        For(j, 1, m){
            int MIN = 0, so = 1;
            For(i, 2, n){
                A = c[i][j] - MIN;
                if(A == res) num += so;
                if(A > res){
                    num = so;
                    res = A;
                }
                if(c[i - 1][j] == MIN) so++;
                if(c[i - 1][j] < MIN){
                    MIN = c[i - 1][j];
                    so = 1;
                }
            }
        }

        For(u, 1, n) For(v, u + 1, n){
            f[0] = g[0] = 0;
            For(i, 1, m) {
                f[i] = r[u][i] + r[v][i];
                g[i] = c[v - 1][i] - c[u][i];
            }

            int MAX = g[1] - f[0]; so = 1;
            For(i, 2, m){
                A = g[i] + f[i] + MAX;
                if(A == res) num += so;
                if(A > res){
                    num = so;
                    res = A;
                }
                if(g[i] - f[i - 1] == MAX) so++;
                if(g[i] - f[i - 1] > MAX){
                    MAX = g[i] - f[i - 1];
                    so = 1;
                }
            }
        }
        cout << res << " " << num << endl;

    }

    return 0;
}

Code mẫu của skyvn97

#include<bits/stdc++.h>
#define  MAX   211
#define FOR(i,a,b) for (int i=(a);i<=(b);i=i+1)
#define FORD(i,b,a) for (int i=(b);i>=(a);i=i-1)
#define REP(i,n) for (int i=0;i<(n);i=i+1)
#define fi   first
#define se   second
using namespace std;
typedef pair<int,int> ii;
int m,n;
int prev[MAX];
int a[MAX][MAX],s[MAX][MAX];
ii tmp[MAX];
void update(ii &a,const ii &b) {
    if (a.fi<b.fi) a=b;
    else if (a.fi==b.fi) a.se+=b.se;
}
void init(void) {
    scanf("%d",&m);
    scanf("%d",&n);
    FOR(i,1,m) FOR(j,1,n) {
        scanf("%d",&a[i][j]);
        if (a[i][j]<1) a[i][j]=-1;
        s[i][j]=s[i-1][j]+a[i][j];
    }
}
ii tworow(int x,int y) {
    //printf("CHOOSE %d %d\n",x,y);
    ii ret=ii(-2,0);
    if (x==y) {
        ii here=ii(a[x][1],1);
        update(ret,here);
        FOR(i,2,n) {
            if (here.fi<0) here=ii(a[x][i],1);
            else here=ii(here.fi+a[x][i],here.se+(here.fi==0));
            update(ret,here);
        }
        //printf("CHOOSE %d %d is %d %d\n",x,y,ret.fi,ret.se);
        return (ret);
    }
    if (x+1==y) {
        ii here=ii(a[x][1]+a[y][1],1);
        update(ret,here);
        FOR(i,2,n) {
            if (here.fi<0) here=ii(a[x][i]+a[y][i],1);
            else here=ii(here.fi+a[x][i]+a[y][i],here.se+(here.fi==0));
            update(ret,here);
        }
        //printf("CHOOSE %d %d is %d %d\n",x,y,ret.fi,ret.se);
        return (ret);
    }
    int sx=a[x][1];
    int sy=a[y][1];
    int fst=1;
    int lst=0;
    FOR(i,2,n) {
        sx+=a[x][i];
        sy+=a[y][i];
        ii cur=ii(sx+sy+s[y-1][1]-s[x][1]+s[y-1][i]-s[x][i],i);
        while (fst<=lst && tmp[lst].fi<cur.fi) lst--;
        lst++;
        tmp[lst]=cur;
    }
    FORD(i,lst,fst) if (i==lst || tmp[i].fi>tmp[i+1].fi) prev[i]=1; else prev[i]=prev[i+1]+1;
    update(ret,ii(tmp[fst].fi,prev[fst]));
    int delta=0;
    FOR(i,2,n-1) {
        while (fst<=lst && tmp[fst].se<=i) fst++;
        assert(fst<=lst);
        delta+=-(s[y][i-1]-s[x-1][i-1])+(s[y-1][i]-s[x][i]);
        update(ret,ii(tmp[fst].fi+delta,prev[fst]));
    }
    FOR(i,1,n) update(ret,ii(s[y][i]-s[x-1][i],1));
    return (ret);
}
void process(void) {
    ii res=ii(-2,0);
    FOR(i,1,m) FOR(j,i,m) update(res,tworow(i,j));
    printf("%d %d\n",res.fi,res.se);
}
int main(void) {
#ifndef ONLINE_JUDGE
    freopen("tmp.txt","r",stdin);
#endif
    int t;
    scanf("%d",&t);
    REP(zz,t) {
        init();
        process();
    }
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.