P1472 奶牛家譜 Cow Pedigrees
阿新 • • 發佈:2018-11-10
太精妙,留著以後慢慢消化
https://www.luogu.org/problemnew/show/P1472
法一:
我們一層一層地來推,列舉層數,然後再列舉這一層選擇的奶牛的個數(必須是偶數個的,因為我第一層已經處理好了),然後再列舉上一層選擇的奶牛的個數(也必須是偶數的,因為我把第二層也特殊處理了,就可以從第三層開始了),但是發現一共要選擇n個奶牛,所以不得不再加一維目前總共選擇的奶牛的數量,也就是加一層迴圈來列舉v罷了;現在就是重點!!!假設上一層選擇了m只奶牛,這一層選擇了j只奶牛,那麼m必須滿足m>=j/2(因為二叉樹的性質),假設上一層的狀態為f[i-1][m][v-j],也就是i-1層選擇了m只奶牛,前i-1層總共選擇了v-j只奶牛的方案總數,這時第i層就是選擇了j只奶牛了,第i層的j只奶牛和第i-1層的m只奶牛互相找媽媽,那麼可以選擇的方案總數就是C(m,j/2)*f[i-1][m][v-j],最後再統計就可以了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll ,ll > P; #define INF 0xf3f3f3f const int Max=int(1000+10); const int mol=9901; int n,k,dp[100+10][200+10][200+10],w[200+10][200+10]; int main() { while(~scanf("%d%d",&n,&k)) { w[0][0]=1; dp[1][1][1]=1; dp[2][2][3]=1; for(int i=1;i<=n;i++) for(int j=0;j<=i;j++) if(j==0||i==j) w[i][j]=1; else w[i][j]=(w[i-1][j]+w[i-1][j-1])%mol; for(int i=3;i<=k;i++) for(int j=2;j<=(n/2+1);j+=2) for(int x=j+1;x<=n;x++) for(int y=j/2;y<=n/2+1;y++) if(y%2==0) dp[i][j][x]+=w[y][j/2]*dp[i-1][y][x-j]%mol; ll ans=0; for(int i=1;i<=n;i++) ans+=dp[k][i][n]; printf("%lld\n",ans%mol); } return 0; }
法二:
採用記憶化搜尋來解決這道題。
我們規定左子樹必須正好滿足要求,即左子樹高度為y-1,而右子樹高度小於等於y-1(如果左右子樹高度不等,則左右子樹可以互換,方案乘以2)然後我們用兩個for迴圈分別列舉左子樹的節點數與右子樹的高度值(小於等於y-1),利用乘法原理狀態轉移。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll ,ll > P; #define INF 0xf3f3f3f const int Max=int(1000+10); #define MOD 9901 bool bVis[212][112]; int dp[212][112]; int n, m; int dfs(int cnt, int height) { if (bVis[cnt][height]) return dp[cnt][height]; if (cnt == 1) return height == 1; bVis[cnt][height] = true; if (height > (cnt + 1) / 2) return 0; if (height <= 1) return 0; int& state(dp[cnt][height]); for (int i(1); i < cnt; i += 2) { for (int j(1); j < height; ++j) { state += dfs(i, height - 1) * dfs(cnt - i - 1, j); state %= MOD; if (height - 1 != j)//如果高度相等,那麼互換反而會導致方案重複(不妨試著模擬一下或者輸出引數) { state += dfs(i, height - 1) * dfs(cnt - i - 1, j); state %= MOD; } } } return state; } int main() { scanf("%d%d", &n, &m); printf("%d\n", dfs(n, m)); return 0; }