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

       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;
	}
 } 


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

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

    特记下,以备后日回顾。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值