HDU4689Derangement (動態規劃)
題目連結:傳送門
題意:
對於一個由1~n組成的長度為n的序列來說它有n!種排法,我們定義初始的排列為1,2,3,...,n對於後續的排列如果a[i]>i則用'+'表示。a[i]<i用'-'表示,給定一個長度為n的由'+'與'-'組成的字串,問滿足這個條件的排列有多少種。
分析:
設dp[i][j]表示前i個字元中有j個'+'沒有排,'-'排完了的方案數。那麼我們可以根據字元的正負分成兩種情況來考慮。
1.a[i]='+':那麼一種情況就是前面有j-1個加號沒有放,而且這個加號也不放,或者前面已經有j個加號沒有放,那麼我們這個加號如果也不放的話就要把這個數放在前面j個加號沒有放的位置上,有j種可能。
因此這時dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*j.
2.a[i]='-':同樣的一種情況就是前面已經有j+1個加號,我們需要把前面這個數放在前面的加號沒有放的位置,又要從前面加號沒有放的位置選一個放在這個位置一共j*j種方案,還有一種是如果前面有j個加號沒有放的話我們就只需要從這j個數種選一個放在這個位置上即可。,因此此時dp[i][j]=dp[i-1][j+1]*j*j+dp[i-1][j]*j;
程式碼如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 30;
typedef long long LL;
LL dp[maxn][maxn];
char s[maxn];
int main()
{
while(~scanf("%s",s)){
int len = strlen(s);
memset(dp,0,sizeof(dp));
dp[0][0]=1LL;
for(int i=1;i<=len;i++){
if(s[i-1]=='+'){
for(int j=1;j<=len;j++){
dp[i][j]+=dp[i-1][j-1];
dp[i][j]+=dp[i-1][j]*(LL)j;
}
}
if(s[i-1]=='-'){
for(int j=1;j<=len;j++){
dp[i][j-1]+=dp[i-1][j]*(LL)j*j;
dp[i][j]+=dp[i-1][j]*(LL)j;
}
}
}
printf("%I64d\n",dp[len][0]);
}
return 0;
}
相關文章
- 【動態規劃(一)】動態規劃基礎動態規劃
- 動態規劃動態規劃
- 動態規劃分析動態規劃
- 動態規劃(DP)動態規劃
- 動態規劃初步動態規劃
- 模板 - 動態規劃動態規劃
- 動態規劃法動態規劃
- 演算法系列-動態規劃(1):初識動態規劃演算法動態規劃
- 淺談動態規劃動態規劃
- 有關動態規劃動態規劃
- 動態規劃小結動態規劃
- 動態規劃初級動態規劃
- 動態規劃講義動態規劃
- 好題——動態規劃動態規劃
- 3.動態規劃動態規劃
- 動態規劃-----線性動態規劃
- 動態規劃專題動態規劃
- 區間動態規劃動態規劃
- 動態規劃題單動態規劃
- 雙序列動態規劃動態規劃
- 動態規劃 總結動態規劃
- 動態規劃方法論動態規劃
- 動態規劃位置hdu 4540 威威貓系列故事——打地鼠(動態規劃)動態規劃
- 動態規劃之數的劃分動態規劃
- 禮物的最大價值(一維動態規劃&二維動態規劃)動態規劃
- [leetcode] 動態規劃(Ⅰ)LeetCode動態規劃
- 動態規劃練習題動態規劃
- 關於動態規劃法動態規劃
- 動態規劃之理論分析動態規劃
- 斜率優化動態規劃優化動態規劃
- 【動態規劃】買賣股票動態規劃
- 動態規劃演算法動態規劃演算法
- 動態規劃解題方法動態規劃
- 大盜阿福(動態規劃)動態規劃
- 動態規劃做題思路動態規劃
- 演算法_動態規劃演算法動態規劃
- 【PAT】5. 動態規劃動態規劃
- 動態規劃入門篇動態規劃