题意:

  给你一个含n个字符的字符串,字符为'D'时表示小于号,字符为“I”时表示大于号,字符为“?”时表示大小于都可以。比如排列 {3, 1, 2, 7, 4, 6, 5} 表示为字符串 DIIDID。任务是计算所有能产生给定字符串的序列数量,每个序列含n+1个数字,分别为1~n+1,即从1开始且不重复。

思路:DP计数。如下步骤

1)将规模n降低,使得对于每个i (1<=i<=n)都可以依靠i-1的结果来计算。最小规模为1个符号,决定两个数字的序列。

2)考虑对于具有i个数字的序列(值从1~i),指定第i个数字为j (1<=j<=i+1),计算所产生的序列数量。那么dp[i][j]表示着具有i个数字的序列,若最后一个数字为j时,所有可能的序列数量。那么dp[i][i+1]就统计了具有i个数字的且满足前i个要求的序列数量。

3)分两种情况:

第一种是第i个为I(小于号,升序):dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + .. + dp[i-1][1]。

另一种是第i个为D(大于号,降序): dp[i][j] = dp[i-1][i] + dp[i-1][i-1] + ... + dp[i-1][j]。

  分析第一个式子,假设前面i个数字所能产生的可能已经知道,那么直接将j加在最后面就行了。比如:序列3>2<4>1  共4个数字和3个符号,假设第4个符号为<,那么现在考虑第5个数字,要算的有dp[4][1] dp[4][2] dp[4][3] dp[4][4] dp[4][5]共5个。dp[4][1]可以想象将1接在序类后,即 3 2 4 1 1,疑问?这不是重复了吗?这样子我们可以将前4个数字中所有大于第5个数字的都加1,就变成4 3 5 2 1,这个序列就合法了吧?是的,对于所有的4个数字的合法序列都这么做。前提是对于第4个数字小于5的所有4数字序列才可以这么考虑。大于等于5的序列再来加1也必定重复。

  分析第二个式子,同样,假设前面i个数字所能产生的可能已经知道,也是加在后面。比如:序列3>1<2 共3个数字和2个符号,假设第3个符号为>,那么现在考虑第4个数字,2大于1,同时还得考虑如上“加一”情况,所以1和2都要考虑。那么要计算的有dp[3][1] dp[3][2] 共2个,dp[3][3]对于我们所假设的情况是非法的。因为大于等于2的都要加一,所以dp[3][2]可能产生的序列之一为 { 3+1, 1,2+1, 2 } 即 {  4, 1,3 ,2 } 。合法!对于其他情况依此法计算。

下面代码实现时利用了前缀和,所以并不是单纯的逐个加,有点技巧在里面,还没领悟透其中原理。

 #include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
const int mod=;
const int N=;
char a[N];
LL sum[N][N]; int main()
{
//freopen("input.txt", "r", stdin);
while(cin>>a)
{
int len=strlen(a);
sum[][] = ; //初始化:没有符号时,假设为只有1个数字,那么就只有序列”1“而已了,结果为1种。 for(int i=; i<=len; i++) //对于第i个符号,就有具有i+1个数字的序列。注:i+1个数字的序列就是1~i+1共i+1个,没有大于i+1的数字。
{
for(int j=; j<=i+; j++)
{ sum[i][j] = sum[i][j-]; //继承第i+1位为j-1的所有情况。 if(a[i-]!='D') //第i个符号是 '<' 。 若是'?'则两个if都执行
sum[i][j] += sum[i-][j-]; if(a[i-]!='I') //第i个符号是 '>'
sum[i][j] += sum[i-][i] - sum[i-][j-] + mod ; //可能出现负的,所以要加mod sum[i][j] %= mod;
}
}
cout<<sum[len][len+]<<endl;
}
return ;
}

AC代码

下面是我的代码,为了好理解不作优化,运算次数应该比上面的少。

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
const int N=;
const int mod=;
unsigned int sum[N][N];
char s[N];
int main()
{
//freopen("input.txt","r",stdin);
while(cin>>s)
{
memset(sum, , sizeof(sum));
int len=strlen(s);
sum[][]=; for(int i=; i<=len; i++) //对于len个符号,有len+1个数字组成。
{
int siz=i+;
if(s[i-]=='I')
{
for(int j=; j<siz; j++) //从小往大的方向累加。
{
sum[i][j]=sum[i][j-];
sum[i][j]=((long long)sum[i][j]+ sum[i-][j-])%mod;
}
}
else if(s[i-]=='D')
{
for(int j=i+; j>; j--) //从大往小的方向累加。
{
sum[i][j]=sum[i][j+];
sum[i][j]=((long long)sum[i][j]+sum[i-][j])%mod;
}
}
else //问号,将上一个位置所有可能相加。
{
long long tmp=;
for(int j=; j<=i; j++)
tmp=((long long)tmp+sum[i-][j])%mod;
for(int j=; j<siz; j++)
sum[i][j]=tmp;
}
}
long long ans=;
for(int i=; i<=len+; i++) //累计所有可能。
ans=((long long)ans+sum[len][i])%mod;
cout<<ans<<endl;
}
return ;
}

int型代码

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
const int N=;
const int mod=;
long long sum[N][N];
char s[N]; int main()
{ //freopen("input.txt","r",stdin);
while(cin>>s)
{
memset(sum, , sizeof(sum));
int len=strlen(s);
sum[][]=; for(int i=; i<=len; i++)
{
int siz=i+;
if(s[i-]=='I')
{
for(int j=; j<siz; j++)
{
sum[i][j]=sum[i][j-];
sum[i][j]+=sum[i-][j-]%mod;
}
}
else if(s[i-]=='D')
{
for(int j=i+; j>; j--)
{
sum[i][j]=sum[i][j+];
sum[i][j]+=sum[i-][j]%mod;
}
}
else
{
long long tmp=;
for(int j=; j<=i; j++)
tmp+=sum[i-][j]%mod;
for(int j=; j<siz; j++)
sum[i][j]=tmp;
}
}
long long ans=;
for(int i=; i<=len+; i++)
ans+=sum[len][i]%mod;
cout<<ans%mod<<endl;
}
return ;
}

longlong型代码(好理解)

HDU 4055 Number String(DP计数)的更多相关文章

  1. HDU 4055 Number String dp

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

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

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

  3. hdu 4055 Number String (基础dp)

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

  4. hdu 4055 Number String

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

  5. HDU 4055 Number String (计数DP)

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

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

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

  7. hdu 4055 Number String(dp)

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

  8. hdu 4055 Number String(递推DP)

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

  9. 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] + ...

随机推荐

  1. POI 中的CellType类型以及值的对应关系

    操作使用POI接口,了解CellType的类型和值的对应关系. CellType 类型 值 CELL_TYPE_NUMERIC 数值型 0 CELL_TYPE_STRING 字符串型 1 CELL_T ...

  2. JVM StackOverflowError vs. OutOfMemoryError

    if the computation in a thread needs a larger Java Virtual Machine stack than is permitted, the Java ...

  3. OpenType字体与TrueType字体的区别

    TrueType采用几何学中二次B样条曲线及直线来描述字体的外形轮廓,其特点是:TrueType既可以作打印字体,又可以用作屏幕显示:由于它是由指令对字形进行描述,因此它与分辨率无关,输出时总是按照打 ...

  4. IIS 6.0曝远程代码执行漏洞CVE-2017-7269

    一.漏洞说明 漏洞编号:CVE2017-7269 影响中间件:IIS6.0 影响服务器版本:windows 2003 R2 二. 环境搭建 虚拟机kali : 192.168.1.2 靶机window ...

  5. 数据库路由中间件MyCat - 源代码篇(14)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 对于表的dataNode对应关系,有个特殊配置即类似dataNode="distributed(d ...

  6. 基于pthread实现读写锁

    读写锁可用于在多线程访问map等数据结构时使用 #include <pthread.h> class ReadWriteLock { public: ReadWriteLock() { p ...

  7. docker-compose是个好东西,越用越香

     回顾前文 前文演示了在单一容器中部署 Nginx和ASP.NET Core WebApp, 正在前文评论区某大牛指出的,容器化部署 nginx+ASP.NET Core 有更符合实战的部署选择:多容 ...

  8. 分类---Logistic Regression

    一 概述 Logistic Regression的三个步骤 现在对为什么不使用均方误差进行分析(步骤二的) 由上图可以看出,当距离目标很远时,均方误差移动速率也很慢,不容易得到好的结果. Discri ...

  9. 给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。

    题目描述 给出每个员工每年薪水涨幅超过5000的员工编号emp_no.薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列. 提示:在s ...

  10. Unity5.5 Lighting Scene

    参考:https://docs.unity3d.com/Manual/GlobalIllumination.html Environment Lighting(环境光) Skybox: 天空盒材质,这 ...