【题解】HDU4689 Derangement(有技巧的计数DP)

【题解】HDU4689 Derangement(有技巧的计数DP)

传送门

呵呵没告诉我多测组数,然后\(n\le 20,7000\mathrm{ms}\)我写了个状压上去T了

题目大意:

要你求错排的方案数,但要求\(i\)位上的数比\(i\)大/小。大小关系用正负号告诉你,读入一个字符串。

\(O(n2^n)\)

\(dp(s)\)表示已经放了\(|s|\)个数进去,放的数占满了\(s\)中的位置的方案数

转移太显然直接贴代码

//@winlere
#include
#include
#include
#include
#define DE(s) cerr<<(#s)<<"="<<(s)<>i&1){
                  if(c[i]=='+'&&cnt>i+1) dp[t]+=dp[t^(1<

过不了 别想了

\(O(n^2)\)

考虑+号是一个后缀性的匹配,-号是一个前缀型的匹配。也就是说我们不可能直接把数给选好,要在后面再进行选择。这启发我可以设这样的状态:

\(dp(i,j)\)表示已经考虑前\(i\)个符号,但是需要从后面拉来\(j\)\(>i\)数来凑齐前面的\(“+”\)

当前是负号:

  • 当前位置上的数拿来匹配前面的+
    \[ dp(i,j)\leftarrow dp(i-1,j+1)((i-1)-(sum(+)-(j+1))-sum(-))(j+1) \]

  • 当前位置上的数不匹配前面的+
    \[ dp(i,j)\leftarrow dp(i-1,j)((i-1)-(sum(+)-j)-sum(-)) \]

当前是正号

  • 当前位置上的数拿来匹配前面一个+
    \[ dp(i,j)\leftarrow dp(i-1,j)j \]

  • 当前位置上的数不匹配
    \[ dp(i,j)\leftarrow dp(i-1,j-1) \]

复杂度\(O(n^2)\)

//@winlere
#include
#include
#include
#include
#define DE(s) cerr<<(#s)<<"="<<(s)<

你可能感兴趣的:(【题解】HDU4689 Derangement(有技巧的计数DP))