【BZOJ2484】[SDOI2011]打地鼠(暴力)
阿新 • • 發佈:2018-11-01
getch 復雜 優秀 數據 ++i define 成了 turn char 顯然也是合法的,等價於我們把\(C\)列每次一起砸就好了。
那麽分開枚舉\(R\)和\(C\)再\(\mbox{check}\)就行了,這樣子暴力的復雜度是\(O(n^4)\)就可以過了。也就是\(O(n)\)枚舉,\(O(n^2)\)考慮所有位置,\(O(n)\)刪掉當前位置對於後面的限制。
【BZOJ2484】[SDOI2011]打地鼠(暴力)
題面
BZOJ
洛谷
題解
看到數據範圍這題就應該是一個暴力題了。
先考慮假如我們知道了錘子的大小\(R*C\),那麽顯然只需要從左上角開始從左往右從上往下一個個砸就行了,因為你砸到當前位置之後左上角一定沒有限制了,只有當前這個位置還有限制。所以直接暴力就是\(O(n^6)\)的了。似乎可以\(BIT\)之類的優化一下,差不多可以做到\(O(n^4log^2n)\)?
然後不夠優秀,我們想想,枚舉\(R*C\)之後限制是考慮左上角是否都變成了\(0\)。
如果我們\(R*1\)可以把東西砸完,即一行行的砸是能夠符合條件的,並且\(1*C\)也能夠砸完,即一列列也是滿足條件的,那麽\(R*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]打地鼠(暴力)