NOJ1682非递减字符串问题 简单dp

来源:互联网 发布:mac retina 13寸壁纸 编辑:程序博客网 时间:2024/05/16 07:10

       6.13晚,闲来无事,想着既然开始写博客,不如从简单的记起,把以前做过的一些有印象的题目记下来,于是有了此篇博客。

    话不多说,进入正题。此题是一道动态规划(dp)的题目,对于大牛来说,属于信手拈来的水题,对于我这等刚踏上acm之路的新手来说,没有思路简直难于上青天。但在接触多了此类题目之后,还是很容易发现此类题目解题技巧。题目:

非递减字符串问题

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 81920 KByte
总提交 : 227            测试通过 : 46 

比赛描述

在非递减字符串中,

从左到右的字符依次按ASC码非递减排列,

例如abcd其他4个字符组成的非递减字符串还有aaaaaabbaaababcc等。现在假设字符串由abcdefghi

j10个字符组成。请你编程确定特定长度的非递减字符串的数目。在非递减字符串中,

从左到右的字符依次按ASC码非递减排列,例如abcd其他4个字符组成的非递减字符串还有aaaaaabb

aaababcc等。现在假设字符串由a、bcdefghij10

个字符组成。请你编程确定特定长

度的非递减字符串的数目。

在非递减字符串中,从左到右的字符依次按ASC码非递减排列,例如abcd,其他4个字符组成的非递减字符串还有aaaa,aabb,aaab,abcc等。现在假设字符串由a、b、c、d、e、f、g、h、i、j等10个字符组成。请你编程确定特定长度的非递减字符串的数目。



输入

输入包括多个测试用例,首先给出测试用例数P(1≤P≤1000),接着给出P个测试用例。每一个测试用例包括一行,给出以空格分隔的两个整数,第1个整数表示测试用例序号,第二整数表示字符串的长度N(1≤N≤64)。

输出

输出包括多行,对于每个测试用例输出一行,输出以空格分隔的两个整数,第1个整数为测试用例序号,第二整数给出长度为N的非递减字符串数目。

样例输入

2
1 4
2 3

样例输出

1 715
2 220

    题目分析:题目给出字符串的长度,要求求出非递减字符串的个数。对于此类问题,应该从状态转移方程入手。

    解题方法:首先构造dp数组,dp[i][j] i指长度为i , j范围是1-10,解释:dp[i][1]是指字符串长度为i时,以字符串a为结尾的字符串的个数,最终输入n的返回结果即为dp[1]到dp[10]的累加。

    然后最为关键的一步是状态方程的推导,此题的状态方程为:dp[i][j]=dp[i][j-1]+dp[i-1][j]。以dp[3,2]=dp[3,1]+dp[2,2]为例,dp[3,2]指的是长度为3末尾是b的字符串个数,dp[2,2]指的是长度为2末尾是b的字符串个数,dp[3,1]指的是长度为3末尾是a的字符串个数,长度为3末尾为b的个数就等于长度为2末尾为b的个数(由二到三只需在末尾加上b即可数量相同)加上长度为3末尾为a的个数(即将末尾的a转换为b)。

    最后贴上代码:

#include<iostream>#include<string.h>using namespace std;const int maxn=65;long long dp[maxn][maxn]; //构造一个dp数组 int main()          //dp[i][j] i指长度为i  j范围是1-10  意思指 以a(1) 结尾的字符串的个数 //而所求结果就是 dp[n][1]-dp[n][10]的累加  {memset(dp,0,sizeof(dp));for(int i=1;i<=10;i++)dp[1][i]=1;int T;cin>>T;while(T--){long long Case,n,res=0;cin>>Case>>n;for(int i=2;i<=n;i++){for(int j=1;j<=10;j++)dp[i][j]=dp[i][j-1]+dp[i-1][j];}for(int j=1;j<=10;j++)res+=dp[n][j];cout<<Case<<" "<<res<<endl;} } 


    重复上文提过的观点,在见多识广的大牛前,这些题目还真的是水题,但对于初学者来说还是得花费时间去理解掌握。总结下来,还是刷题量太少,见识太短浅。解决方法唯有刷题刷题再刷题。

    仔细评估一下自己现在的水平,还是急需提高,老话重提,征途漫漫啊。

    特记下,以备后日回顾。

0 0
原创粉丝点击