1. 程式人生 > >【BZOJ2484】[SDOI2011]打地鼠(暴力)

【BZOJ2484】[SDOI2011]打地鼠(暴力)

getch 復雜 優秀 數據 ++i define 成了 turn char

【BZOJ2484】[SDOI2011]打地鼠(暴力)

題面

BZOJ
洛谷

題解

看到數據範圍這題就應該是一個暴力題了。
先考慮假如我們知道了錘子的大小\(R*C\),那麽顯然只需要從左上角開始從左往右從上往下一個個砸就行了,因為你砸到當前位置之後左上角一定沒有限制了,只有當前這個位置還有限制。所以直接暴力就是\(O(n^6)\)的了。似乎可以\(BIT\)之類的優化一下,差不多可以做到\(O(n^4log^2n)\)
然後不夠優秀,我們想想,枚舉\(R*C\)之後限制是考慮左上角是否都變成了\(0\)
如果我們\(R*1\)可以把東西砸完,即一行行的砸是能夠符合條件的,並且\(1*C\)也能夠砸完,即一列列也是滿足條件的,那麽\(R*C\)

顯然也是合法的,等價於我們把\(C\)列每次一起砸就好了。
那麽分開枚舉\(R\)\(C\)\(\mbox{check}\)就行了,這樣子暴力的復雜度是\(O(n^4)\)就可以過了。也就是\(O(n)\)枚舉,\(O(n^2)\)考慮所有位置,\(O(n)\)刪掉當前位置對於後面的限制。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 105
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,m,a[MAX][MAX],s[MAX][MAX];
int R,C,sum;
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            sum+=(a[i][j]=read());
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=n;++j)
            for(int k=1;k<=m;++k)
                s[j][k]=a[j][k];
        for(int j=1;j<=m;++j)
            for(int k=1;k+i-1<=n;++k)
                for(int l=k+i-1;l>=k;--l)
                    s[l][j]-=s[k][j];
        bool fl=true;
        for(int j=1;j<=m;++j)
            for(int k=1;k<=n;++k)
                if(s[k][j])fl=false;
        if(fl)R=i;
    }
    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=n;++j)
            for(int k=1;k<=m;++k)
                s[j][k]=a[j][k];
        for(int j=1;j<=n;++j)
            for(int k=1;k+i-1<=m;++k)
                for(int l=k+i-1;l>=k;--l)
                    s[j][l]-=s[j][k];
        bool fl=true;
        for(int j=1;j<=n;++j)
            for(int k=1;k<=m;++k)
                if(s[j][k])fl=false;
        if(fl)C=i;
    }
    printf("%d\n",sum/(R*C));
    return 0;
}

【BZOJ2484】[SDOI2011]打地鼠(暴力)