DP.....
f[i][j]表示前 i 个数还有 j 个+号没有放数字,-号全部放满。
当 i 为+号时:1、当前这个数不放,即放在后面的位置中,f[i][j]+=f[i-1][j-1]。2、当前这个数放在前面的位置中,
f[i][j]+=f[i-1][j]*j。所以f[i][j]=f[i-1][j-1]+f[i-1][j]*j。
当 i 为-号时:1、当前这个数放在后面的位置中,由前面+号未填的数来填-号,f[i][j]+=f[i-1][j]*j。2、当前这个数
放在前面的位置中,前面 j 个空位对应的数放在当前的-号位,当前这个数放在前面未放的+号位,
f[i][j]+=f[i-1][j+1]*j*j。
Derangement
Time Limit: 7000/7000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 838 Accepted Submission(s): 251
Problem Description
A derangement is a permutation such that none of the elements appear in their original position. For example, [5, 4, 1, 2, 3] is a derangement of [1, 2, 3, 4, 5]. Subtracting the original permutation from the derangement, we get the derangement difference [4, 2, -2, -2, -2], where none of its elements is zero. Taking the signs of these differences, we get the derangement sign [+, +, -, -, -]. Now given a derangement sign, how many derangements are there satisfying the given derangement sign?
Input
There are multiple test cases. Process to the End of File.
Each test case is a line of derangements sign whose length is between 1 and 20, inclusively.
Output
For each test case, output the number of derangements.
Sample Input
Sample Output
Author
Zejun Wu (watashi)
Source
2013 Multi-University Training Contest 9
ll dp[N][N];
char s[N];
int main()
{
while(scanf("%s",s)==1)
{
int n=strlen(s);
memset(dp,0,sizeof dp);
dp[0][0]=1;
for(int k=0;k<=n;k++)
{
for(int i=0;i<=n;i++)
{
ll tmp = dp[k][i];
if(tmp==0) continue;
/// printf("dp[%d][%d] = %d\n", k, i, dp[k][i]);
if(s[k]=='+')
{
dp[k+1][i+1] += tmp;
dp[k+1][i] += i * tmp;
}
if(s[k]=='-')
{
dp[k+1][i] += 1ll * i * tmp;
if(i) dp[k+1][i-1] += 1ll * i * i * tmp;
}
}
// putchar(10);
}
printf("%I64d\n", dp[n][0]);
}
}