HDU4055_Number String
题目告诉你在一个排列中,相邻两个数的大小关系。问你排列可能有多少种情况。
DP。
f[i][j]表示将i个数按照前面i-1个大小关系排列且最后一个数位j的排列数有多少个。
这样对于新加入的一个数i+1,我们直接枚举第i+1个数在所有的i+1个数为第几大即可。
注意加入sum数组,不然时间复杂度就是O(N^3)了。
注意不要每次取模,注意不需要long long。注意时间常数。
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1010
#define M 1000000007
using namespace std;
int f[maxn][maxn],sum1[maxn],sum2[maxn];
char s[maxn];
int count(int x)
{
if (x<M) return x;
return x-M;
}
int main()
{
while (scanf("%s",s+1)!=EOF)
{
memset(f,0,sizeof f);
memset(sum1,0,sizeof sum1);
memset(sum2,0,sizeof sum2);
f[1][1]=1,sum1[1]=1,sum2[1]=1;
for (int i=1; s[i]; i++)
{
for (int j=1; j<=i+1; j++)
{
if (s[i]=='?') f[i+1][j]=count(sum1[j-1]+sum2[j]);
else if (s[i]=='I') f[i+1][j]=sum1[j-1];
else if (s[i]=='D') f[i+1][j]=sum2[j];
}
sum1[1]=f[i+1][1];
for (int j=2; j<=i+1; j++) sum1[j]=count(sum1[j-1]+f[i+1][j]);
sum2[i+1]=f[i+1][i+1];
for (int j=i; j>0; j--) sum2[j]=count(sum2[j+1]+f[i+1][j]);
}
int ans=0,n=strlen(s+1)+1;
for (int i=1; i<=n; i++) ans=count(ans+f[n][i]);
printf("%d\n",ans);
}
return 0;
}
如有转载,请注明出处(http://www.cnblogs.com/lochan)