1. 程式人生 > >BZOJ-2241: [SDOI2011]打地鼠 (模擬+枚舉)

BZOJ-2241: [SDOI2011]打地鼠 (模擬+枚舉)

位置 1.0 log pan 每次 規格 tdi 工作 多次

2241: [SDOI2011]打地鼠

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 1434 Solved: 909
[Submit][Status][Discuss]

Description

打地鼠是這樣的一個遊戲:地面上有一些地鼠洞,地鼠們會不時從洞裏探出頭來很短時間後又縮回洞中。玩家的目標是在地鼠伸出頭時,用錘子砸其頭部,砸到的地鼠越多分數也就越高。

遊戲中的錘子每次只能打一只地鼠,如果多只地鼠同時探出頭,玩家只能通過多次揮舞錘子的方式打掉所有的地鼠。你認為這錘子太沒用了,所以你改裝了錘子,增加了錘子與地面的接觸面積,使其每次可以擊打一片區域。如果我們把地面看做M*N的方陣,其每個元素都代表一個地鼠洞,那麽錘子可以覆蓋R*C區域內的所有地鼠洞。但是改裝後的錘子有一個缺點:每次揮舞錘子時,對於這R*C的區域中的所有地洞,錘子會打掉恰好一只地鼠。也就是說錘子覆蓋的區域中,每個地洞必須至少有1只地鼠,且如果某個地洞中地鼠的個數大於1,那麽這個地洞只會有1只地鼠被打掉,因此每次揮舞錘子時,恰好有R*C只地鼠被打掉。由於錘子的內部結構過於精密,因此在遊戲過程中你不能旋轉錘子(即不能互換R和C)。

你可以任意更改錘子的規格(即你可以任意規定R和C的大小),但是改裝錘子的工作只能在打地鼠前進行(即你不可以打掉一部分地鼠後,再改變錘子的規格)。你的任務是求出要想打掉所有的地鼠,至少需要揮舞錘子的次數。

Hint:由於你可以把錘子的大小設置為1*1,因此本題總是有解的。

Input

第一行包含兩個正整數M和N;

下面M行每行N個正整數描述地圖,每個數字表示相應位置的地洞中地鼠的數量。

Output

輸出一個整數,表示最少的揮舞次數。

Sample Input

3 3

1 2 1

2 4 2

1 2 1

Sample Output


4

【樣例說明】

使用2*2的錘子,分別在左上、左下、右上、右下揮舞一次。

【數據規模和約定】


對於100%的數據,1<=M,N<=100,其他數據不小於0,不大於10^5

HINT

Source

第一輪Day1

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=1005;
 5 int n,K;
 6 int x[MAX],y[MAX],fa[MAX];
 7 inline int read(){
 8     int an=0,x=1;char c=getchar();
 9     while (c<0 || c>9) {if (c==-) x=-1;c=getchar();}
10     while
(c>=0 && c<=9) {an=(an<<3)+(an<<1)+c-0;c=getchar();} 11 return an*x; 12 } 13 double dis(int i,int j){return sqrt((x[i]*1.0-x[j]*1.0)*(x[i]*1.0-x[j]*1.0)+(y[i]*1.0-y[j]*1.0)*(y[i]*1.0-y[j]*1.0));} 14 inline int getfather(int x){return fa[x]==x?x:fa[x]=getfather(fa[x]);} 15 bool feasible(double x){ 16 int i,j,ans=0; 17 for (i=1;i<=n;i++) fa[i]=i; 18 for (i=1;i<=n;i++) 19 for (j=1;j<=n;j++) 20 if (i!=j && dis(i,j)<=x){ 21 int tx=getfather(i),ty=getfather(j); 22 if (tx!=ty) fa[tx]=ty; 23 } 24 for (i=1;i<=n;i++) 25 if (fa[getfather(i)]==i) ans++; 26 return ans<K; 27 } 28 int main(){ 29 freopen ("group.in","r",stdin);freopen ("group.out","w",stdout); 30 int i,j; 31 n=read(),K=read(); 32 for (i=1;i<=n;i++) x[i]=read(),y[i]=read(); 33 double low=0,high=1e10,mid; 34 while (high-low>0.0000001){ 35 mid=(low+high)/2.0; 36 if (feasible(mid)) high=mid; 37 else low=mid; 38 } 39 printf("%.2lf",low); 40 return 0; 41 }

BZOJ-2241: [SDOI2011]打地鼠 (模擬+枚舉)