小小明系列故事——遊戲的煩惱
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 841 Accepted Submission(s): 296
Problem Description
小小明最近在玩一款遊戲,它由n*m大小的矩陣構成,矩陣上會隨機產生一些黑色的點,這些點它們可能會連在一起也可能會分開,這些點的個數沒有限制,但
是每個1*1方格中最多隻可能有一個黑點產生。遊戲要求玩家以最短的時間用x*y的小矩陣覆蓋這個大矩陣,覆蓋的要求有以下2點:
1. x*y大小的小矩陣內必須有x*y個黑點。
2. 多個小矩陣可以重疊,但是每個小矩陣放置的位置必須是獨一無二的,即不同的小矩陣內的黑點不能完全相同。例如1*2的矩陣可以橫著放,也可以豎著放,這兩種方法是不同的,即使它們可能共用黑點。
小小明是個粗心的孩子,他嘗試了很多遍都無法將所有的符合要求的小矩陣找到,聰明的你,能不能告訴煩惱中的小小明這個大矩陣裡有多少個滿足要求的小矩陣呢?
1. x*y大小的小矩陣內必須有x*y個黑點。
2. 多個小矩陣可以重疊,但是每個小矩陣放置的位置必須是獨一無二的,即不同的小矩陣內的黑點不能完全相同。例如1*2的矩陣可以橫著放,也可以豎著放,這兩種方法是不同的,即使它們可能共用黑點。
小小明是個粗心的孩子,他嘗試了很多遍都無法將所有的符合要求的小矩陣找到,聰明的你,能不能告訴煩惱中的小小明這個大矩陣裡有多少個滿足要求的小矩陣呢?
Input
題目有多組測試資料(不多於100個);
每組測試資料的第一行包含2個正整數n和m,然後第二行是x和y(n,m,x,y的意思如題),接下來n行,每行m個字元,其中’ * ’表示黑點,’ . ’表示空白。
n和m為0則結束輸入。
[Technical Specification]
0 < n, m <= 2000
0 < x, y <= 1000
每組測試資料的第一行包含2個正整數n和m,然後第二行是x和y(n,m,x,y的意思如題),接下來n行,每行m個字元,其中’ * ’表示黑點,’ . ’表示空白。
n和m為0則結束輸入。
[Technical Specification]
0 < n, m <= 2000
0 < x, y <= 1000
Output
請計算並輸出一共有多少個滿足要求的小矩陣,每組輸出佔一行。
Sample Input
2 3
1 2
**.
.**
0 0
Sample Output
3
Source
剛開始進行了個普通的匹配,O(∩_∩)O~,就知道會TLE,╮(╯▽╰)╭,就是這麼無奈呀!
貼一下自己丑陋的程式碼吧..
程式碼:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 using namespace std; 5 const int maxn=2005; 6 char map[maxn][maxn]; 7 int n,m; 8 bool match(int posx,int posy,int x,int y) 9 { 10 int i,j; 11 if(posx+x>n||posx<0||posy+y>m||posy<0) 12 return 0; 13 for( i=posx; i<posx+x ; i++ ){ 14 for( j=posy ; j<posy+y ; j++ ) { 15 if(map[i][j]!='*')return false; 16 } 17 } 18 return true; 19 } 20 21 int work(int x,int y) 22 { 23 int i,j,cnt=0; 24 for(i=0;i<n;i++){ 25 for(j=0;j<m;j++){ 26 if(match(i,j,x,y)) cnt++; 27 if(match(i,j,y,x)) cnt++; 28 } 29 } 30 return cnt; 31 } 32 int main() 33 { 34 int x,y,i; 35 while(scanf("%d%d",&n,&m)!=EOF,n+m!=0) 36 { 37 scanf("%d%d",&x,&y); 38 for(i=0;i<n;i++) 39 scanf("%s",map[i]); 40 printf("%d\n",work(x,y)); 41 } 42 return 0; 43 }
然後統計了一下,dp...簡單的dp
程式碼: 不過依舊還是很挫,寫到了680ms....
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 using namespace std; 5 const int maxn=2005; 6 char map[maxn][maxn]; 7 int dp[maxn][maxn]; 8 int n,m; 9 void init() 10 { 11 int i,j,cnt=0; 12 memset(dp,0,sizeof(dp)); 13 for(i=1;i<=n;i++) { 14 for(j=1;j<=m;j++) { 15 if(map[i][j-1]=='*')cnt++; 16 dp[i][j]=cnt+dp[i-1][j]; 17 } 18 cnt=0; 19 } 20 } 21 int work(int x,int y){ 22 int i,j,cnt=0; 23 for(i=1;i+x<=n;i++){ 24 for(j=1;j+y<=m;j++){ 25 int tem=dp[i+x][j+y]-dp[i-1][j+y]-dp[i+x][j-1]+dp[i-1][j-1]; 26 if(tem==((x+1)*(y+1)))cnt++; 27 } 28 } 29 return cnt; 30 } 31 int main() 32 { 33 int x,y,i; 34 while(scanf("%d%d",&n,&m),n+m!=0) 35 { 36 scanf("%d%d",&x,&y); 37 x--,y--; 38 for(i=1;i<=n;i++) 39 scanf("%s",map[i]); 40 init(); 41 if(x==y) printf("%d\n",work(x,y)); 42 else printf("%d\n",work(x,y)+work(y,x)); 43 44 } 45 return 0; 46 }