2013 Multi-University Training Contest 9
题意:定义初始排列为1、2、…、n,定义一个n排列A[], 若i>A[i]表示为’+’,i
新队伍组队第一场啊,有DP大佬队友的感觉真是好。
f[i][j]表示放置用前i个数字放置前i个位置,填满了所有’-‘,剩下j个’+’没填(也相当于有j个数字要放置到第i+1~n位)的总方案数。
初始条件f[0][0]=1,转移如下:
- 当a[i]为’+’
- 当前数字i在前面挑一个’+’放置,此时当前’+’未填,j不变:f[i][j]+=f[i-1][j]*j
- 当前数字i不放置,此时当前’+’未填,j增加:f[i][j]+=f[i-1][j-1]
- 当a[i]为’-‘
- 在前j个未放置的数字中挑选一个放置到当前位置,当前数字i不放置,此时j不变:f[i][j]+=f[i-1][j]
- 在前j+1个未放置的数字中挑选一个放置到当前位置,当前数字i在前面挑一个’+’放置,此时j减少:f[i][j]+=f[i-1][j+1]*(j+1)*(j+1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=20+5; typedef long long lint; lint f[maxn][maxn]; char s[maxn]; int main() { while(scanf("%s", s+1)!=EOF) { int n=strlen(s+1); memset(f, 0, sizeof f); f[0][0]=1; for(int i=1; i<=n; i++) for(int j=0; j<=i; j++) { if(s[i]=='+') { f[i][j]+=f[i-1][j]*j; if(j) f[i][j]+=f[i-1][j-1]; } else f[i][j]+=(f[i-1][j]*j+f[i-1][j+1]*(j+1)*(j+1)); } printf("%lld\n", f[n][0]); } return 0; }
|