计数dp-hdu-4054-Number String
题目链接:
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的更多相关文章
- 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] + ...
- HDU 4055 Number String dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4055 Number String Time Limit: 10000/5000 MS (Java/O ...
- hdu 4055 Number String(有点思维的DP)
Number String Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 4055 Number String (基础dp)
Number String Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 4055 Number String
Number String http://acm.hdu.edu.cn/showproblem.php?pid=4055 Time Limit: 10000/5000 MS (Java/Others) ...
- HDU 4055 Number String(DP计数)
题意: 给你一个含n个字符的字符串,字符为'D'时表示小于号,字符为“I”时表示大于号,字符为“?”时表示大小于都可以.比如排列 {3, 1, 2, 7, 4, 6, 5} 表示为字符串 DIIDID ...
- HDU 4055 Number String (计数DP)
题意:由数字1到n组成的所有排列中,问满足题目所给的n-1个字符的排列有多少个,如果第i字符是‘I’表示排列中的第i-1个数是小于第i个数的. 如果是‘D’,则反之. 析:dp[i][j] 表示前 i ...
- hdu 4055 Number String(dp)
Problem Description The signature of a permutation is a string that is computed as follows: for each ...
- HDU 4055 Number String:前缀和优化dp【增长趋势——处理重复选数】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4055 题意: 给你一个由'I', 'D', '?'组成的字符串,长度为n,代表了一个1~n+1的排列中 ...
- hdu 4055 Number String(递推DP)
给一个只含‘I','D','?'三种字符的字符串,I表示当前数字大于前面的数字,D表示当前的数字小于前面一位的数字,?表示当前位既可以小于又可以大于. 问1~n的排列中有多少个满足该字符串. http ...
随机推荐
- 工厂方法模式(Factory Method)
1.本质:延迟到子类来选择实现 2.示意图: 3.主要功能: 让父类在不知道具体实现的情况下,完成自身功能的调用 类似于注入 4.备注: 1.工厂方法中,通常父类是一个抽象类,里面包含创建对象的抽象工 ...
- php配置虚拟主机的配置步骤(hosts、httpd.conf、vhosts.conf)1.配置本地的dns文件2.配置apache的主配置文件3.配置Apache的虚拟主机
1.域名解析(DNS) 找到C:\Windows\System32\drivers\etc目录下的hosts文件,在里面进行添加对应的内容
- 安装 mysql server
三个月前向公司申请了一台服务器单独给我用,作为部署我写的自动发布工具的服务器.同事不久前在我这台服务器上装了个数据库,今天上去查了一下,用不了,只有information_schema和test两个数 ...
- BZOJ 1019 汉诺塔
Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一个塔状的锥形体. 对汉诺塔的一次合法的操 ...
- 【技术贴】7-zip 7z关联右键菜单后右键不弹出菜单的解决办法
解决7z,7zip右键菜单 失效 右键菜单 无法弹出右键菜单 不正常 右键菜单 sb等各种疑难杂症. 1.首先先去7z的选项里面把右键关联给设置了. 用的好好的7z,正吃着火锅唱着歌忽然发现右键单文件 ...
- codeforces B. Prison Transfer
题意:输入n,t,c,再输入n个数,然后问有多少个连续区间内的最大值小于等于t; #include <cstdio> #include <cstring> #include & ...
- hdu 5144 NPY and shot
http://acm.hdu.edu.cn/showproblem.php?pid=5144 题意:给你初始的高度和速度,然后让你求出水平的最远距离. 思路:三分枚举角度,然后根据公式求出水平距离. ...
- Area
http://poj.org/problem?id=1265 #include<cstdio> #include<istream> #include<algorithm& ...
- Spring Framework Reference,Documentation,spring英文文档.pdf 官方文档
直接上链接:http://files.cnblogs.com/files/kongkaikai/spring-framework-reference.pdf 官网链接:http://docs.spri ...
- libevent带负载均衡的多线程使用示例
功能: 主线程根据负载工作线程负载均衡算法,每隔一秒钟向特定的工作线程发送一条字符串信息,工作线程简单的把字符串信息打开出来. Makefile eventtest : eventtest.c ...