题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4055

题目大意:

给一个只含‘I','D','?'三种字符的字符串,I表示当前数字大于前面的数字,D表示当前的数字小于前面一位的数字,?表示当前位既可以小于又可以大于。

问1~n的排列中有多少个满足该字符串。

解题思路:

计数dp.

dp[i][j]表示长度为i字符串,最后一个数为j时,能达到满足给定字符串的1~i+1的排列个数。

转移方程:

当S[i]='I'时,当前如果为j的话,前面的一位肯定要小于j,dp[i][j]+=Mi[j-1] ; //Mi[i]表示前面一位下标小于等于i dp[][1~i]的和

当S[i]='D'时,dp[i][j]+=(la-Mi[j-1]);  //前一位要大于等于j

当S[i]='?'时,dp[i][j]+=la; //la表示前一位所有的状态总和.

注意递推的时候,前i位只和相对大小有关,与绝对大小无关,所以都用1~i表示,当增加一位时,就变成了1~i+1,如果当前为j,前面的小于j的状态不变,大于等于j的状态k所表示的值 现在表示k+1的值,这样就从1~i等价的转化成了1~i+1,这样考虑就不用考虑1~n的放法了,递推到n位时肯定都是1~n了。

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<string>
using namespace std; const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const double PI = acos(-1.0);
typedef __int64 ll;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/ #define M 1000000007
#define Maxn 1100
char sa[Maxn];
int dp[Maxn][Maxn]; //dp[i][j]表示有i个字符,当前数字为j时,所有的总数
//注意有i个字符说明前面一共有1~i+1个不同的数字,dp[i-1]共有1~i个数字,
//建立递推时,如果当前为j,则前面小于j的不变,大于等于j的全部加一,这样就从1~i变成了1~i+1
int la;
int Mi[Maxn][2]; //Mi[i]表示上一个dp[i-1]下标小于等于j的值的总和 int main()
{
while(~scanf("%s",sa+1))
{
int len=strlen(sa+1);
for(int i=0;i<=len+10;i++) //初始化
{
Mi[i][0]=Mi[i][1]=0;
for(int j=0;j<=len+10;j++)
dp[i][j]=0;
}
dp[0][1]=1; //没有字符时,有一个数 且这个数为1
la=1;
Mi[1][0]=1; //下标小于等于1的有一个
int pp=0; for(int i=1;i<=len;i++)
{
pp=pp^1; //当前状态
int n=i+1;//当前为可能的取值,注意前面的之和相对大小有关
ll cur=0;
for(int j=1;j<=n;j++) //枚举当前位的数值
{
if(sa[i]=='I') //如果为增的话,前面的肯定是小于j的
dp[i][j]=(dp[i][j]+Mi[j-1][pp^1])%M;
else if(sa[i]=='D') //减的话,前面是大于等于j的,加1后就变成了大于j的了
dp[i][j]=(dp[i][j]+(la-Mi[j-1][pp^1])%M+M)%M;
else //如果无所谓的话,前面所有1-n-1个状态都行
dp[i][j]=(dp[i][j]+la)%M; //用一个la记录
Mi[j][pp]=(Mi[j-1][pp]+dp[i][j])%M;//求出当前的Mi
cur=(cur+dp[i][j])%M; //求出当前的la
}
la=cur; //这题卡常数,多了几个循环都不行
}
ll ans=0;
for(int i=1;i<=len+1;i++) //枚举最后的能够占有的值
ans=(ans+dp[len][i])%M;
printf("%d\n",ans);
}
return 0;
}

计数dp-hdu-4054-Number String的更多相关文章

  1. HDU 4054 Number String

    HDU 4054 Number String 思路: 状态:dp[i][j]表示以j结尾i的排列 状态转移: 如果s[i - 1]是' I ',那么dp[i][j] = dp[i-1][j-1] + ...

  2. HDU 4055 Number String dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4055 Number String Time Limit: 10000/5000 MS (Java/O ...

  3. hdu 4055 Number String(有点思维的DP)

    Number String Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. hdu 4055 Number String (基础dp)

    Number String Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. hdu 4055 Number String

    Number String http://acm.hdu.edu.cn/showproblem.php?pid=4055 Time Limit: 10000/5000 MS (Java/Others) ...

  6. HDU 4055 Number String(DP计数)

    题意: 给你一个含n个字符的字符串,字符为'D'时表示小于号,字符为“I”时表示大于号,字符为“?”时表示大小于都可以.比如排列 {3, 1, 2, 7, 4, 6, 5} 表示为字符串 DIIDID ...

  7. HDU 4055 Number String (计数DP)

    题意:由数字1到n组成的所有排列中,问满足题目所给的n-1个字符的排列有多少个,如果第i字符是‘I’表示排列中的第i-1个数是小于第i个数的. 如果是‘D’,则反之. 析:dp[i][j] 表示前 i ...

  8. hdu 4055 Number String(dp)

    Problem Description The signature of a permutation is a string that is computed as follows: for each ...

  9. HDU 4055 Number String:前缀和优化dp【增长趋势——处理重复选数】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4055 题意: 给你一个由'I', 'D', '?'组成的字符串,长度为n,代表了一个1~n+1的排列中 ...

  10. hdu 4055 Number String(递推DP)

    给一个只含‘I','D','?'三种字符的字符串,I表示当前数字大于前面的数字,D表示当前的数字小于前面一位的数字,?表示当前位既可以小于又可以大于. 问1~n的排列中有多少个满足该字符串. http ...

随机推荐

  1. Tenth Line

    How would you print just the 10th line of a file? For example, assume that file.txt has the followin ...

  2. MVC 文本转换成html显示

    最近在学习ASP.NET MVC,项目中需要将后台传输的HTML文本在前台页面显示:@Html.Raw(HttpUtility.HtmlDecode(ViewBag.DisplayText)).记下来 ...

  3. __call方法简介

    作用:当程序试图调用不存在或不可见的成员方法时,PHP会先调用__call方法来储方法名及参数. __call方法包含两个参数:即方法名和方法参数.其中,方法参数是以数组形式存在的.

  4. js以json形式提交数据,后台接受

    $("#savename").click(function(){ var fananname=$("#editname").val(); var jsonLis ...

  5. 关于存储的--b

    iphone沙箱模型的有四个文件夹,分别是什么,永久数据存储一般放在什么位置,得到模拟器的路径的简单方式是什么. documents,tmp,app,Library. (NSHomeDirectory ...

  6. About JavaScript

    JavaScript Function, Constructor function, Plain Object (expression function, closure) Maintainable ...

  7. Following Orders

    uva124:http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=60题 ...

  8. SHell命令总结

    cat  files-to-copy.txt | xargs -i cp {} /tmp

  9. 12.HTML编辑器(CKEditor、CKFinder集成)

    CKEditor原名为FckEditor,是著名的HTML编辑器,可以在线编辑HTML内容. 配置参考文档:主要将ckeditor中的lang.plugins.skins.ckeditor.js.co ...

  10. 【HDOJ】2222 Keywords Search

    AC自动机基础题. #include <iostream> #include <cstdio> #include <cstring> #include <cs ...