搭積木

小明對搭積木很是感興趣。他的積木都是一樣大小的正立方體。
在搭積木時,小明選取 m 塊積木做爲地基,將他們在桌子上一字排開,中間不留空隙,並稱其爲第0層。
隨後,小明能夠在上面擺放第1層,第2層,……,最多擺放至第n層。擺放積木必須遵循三條規則:ios


規則1:每塊積木必須緊挨着放置在某一塊積木的正上方,與其下一層的積木對齊;
規則2:同一層中的積木必須連續擺放,中間不能留有空隙;
規則3:小明不喜歡的位置不能放置積木。spa


其中,小明不喜歡的位置都被標在了圖紙上。圖紙共有n行,從下至上的每一行分別對應積木的第1層至第n層。每一行都有m個字符,字符多是‘.’或‘X’,其中‘X’表示這個位置是小明不喜歡的。
如今,小明想要知道,共有多少种放置積木的方案。他找到了參加藍橋杯的你來幫他計算這個答案。
因爲這個答案可能很大,你只須要回答這個答案對1000000007(十億零七)取模後的結果。
注意:地基上什麼都不放,也算做是方案之一種。code


【輸入格式】
輸入數據的第一行有兩個正整數n和m,表示圖紙的大小。
隨後n行,每行有m個字符,用來描述圖紙 。每一個字符只多是‘.’或‘X’。blog


【輸出格式】
輸出一個整數,表示答案對1000000007取模後的結果。內存


【樣例輸入1】
2 3
..X
.X.資源


【樣例輸出1】
4虛擬機


【樣例說明1】
成功的擺放有(其中O表示放置積木):
(1)
..X
.X.
(2)
..X
OX.
(3)
O.X
OX.
(4)
..X
.XOstring


【樣例輸入2】
3 3
..X
.X.
...io


【樣例輸出2】
16class


【數據規模約定】
對於10%的數據,n=1,m<=30;
對於40%的數據,n<=10,m<=30;
對於100%的數據,n<=100,m<=100。

 


資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗  < 1000ms

 

記憶化搜索,動態規劃思想,最初是橫向看一行行的去算,複雜度很高,縱向去看會發現,其實就是一條一條的柱子拼在一塊兒,按照題意,要求不能存在中間的柱子比兩邊低,也就是說要麼高度是遞增,要麼是遞減,要麼從某個點向兩側遞減,因此添加一個狀態0表示減1表示增。

代碼:

#include <iostream> #include <vector> #include <cstring>
#define mod 1000000007
using namespace std; char mp[101]; int h[101]; int n,m; int dp[2][101][101]; int dfs(int k,int he,int flag) { if(dp[flag][k][he]) return dp[flag][k][he]; if(flag > 0) { for(int i = he;i <= h[k + 1];i ++) { dp[flag][k][he] = (dp[flag][k][he] + dfs(k + 1,i,flag)) % mod; } for(int i = 0;i <= min(he - 1,h[k + 1]);i ++) { dp[flag][k][he] = (dp[flag][k][he] + dfs(k + 1,i,0)) % mod; } } else { for(int i = 0;i <= min(he,h[k + 1]);i ++) { dp[flag][k][he] = (dp[flag][k][he] + dfs(k + 1,i,0)) % mod; } } return dp[flag][k][he]; } int main() { scanf("%d%d",&n,&m); for(int i = 0;i < n;i ++) { scanf("%s",mp); for(int j = 0;j < m;j ++) { if(mp[j] == 'X') h[j] = max(h[j],i + 1); } } for(int i = 0;i < m;i ++) { h[i] = n - h[i]; } for(int i = 0;i <= h[m - 1];i ++) { dp[0][m - 1][i] = dp[1][m - 1][i] = 1; } int ans = 0; for(int i = 0;i <= h[0];i ++) { ans = (ans + dfs(0,i,1)) % mod; } printf("%d",ans); }

動態規劃

代碼:

#include <iostream> #include <vector> #include <cstring>
#define mod 1000000007
using namespace std; typedef long long ll; char mp[101]; int h[101]; int n,m; int dp[2][101][101]; inline int add(int a,int b) { if(b >= mod - a) return a - mod + b; return a + b; } int main() { scanf("%d%d",&n,&m); for(int i = 0;i < n;i ++) { scanf("%s",mp); for(int j = 0;j < m;j ++) { if(mp[j] == 'X') h[j] = i + 1; } } for(int i = 0;i < m;i ++) { h[i] = n - h[i]; } for(int i = 0;i <= h[0];i ++) { dp[1][0][i] = 1; } for(int i = 1;i < m;i ++) { for(int j = 0;j <= h[i];j ++) { int d = (h[i - 1] < j ? h[i - 1] : j); for(int k = 0;k <= d;k ++) { dp[1][i][j] = add(dp[1][i][j],dp[1][i - 1][k]); } for(int k = j + 1;k <= h[i - 1];k ++) { dp[0][i][j] = add(dp[0][i][j],dp[1][i - 1][k]); dp[0][i][j] = add(dp[0][i][j],dp[0][i - 1][k]); } if(j <= h[i - 1]) dp[0][i][j] = add(dp[0][i][j],dp[0][i - 1][j]); } } int ans = 0; for(int i = 0;i <= h[m - 1];i ++) { ans = add(add(ans,dp[0][m - 1][i]),dp[1][m - 1][i]); } printf("%d",ans); }
相關文章
相關標籤/搜索