2016BIT 小学期 —— 编程珠玑 动态规划基础

1.题目描述

12.编程珠玑

成绩10开启时间2016年09月6日 星期二 11:00
折扣0.8折扣时间2016年09月12日 星期一 23:55
允许迟交关闭时间2016年10月10日 星期一 23:55

你有一条项链,它由 N 个随机排列的红、白和蓝色的珠子组成(3<=N<=350)。下面的例子展示了两条 N=29 时的项链:

             1 2                              1 2
           r b b r                           b r r b
          r         b                       b         b
         r           r                     b           r
        r             r                   w             r
       b               r                 w               w
      b                 b               r                 r
      b                 b               b                 b
      b                 b               r                 b
       r               r                 b               r
        b             r                   r             r
         b           r                     r           r
           r       r                         r       b
             r b r                            r r w
          Figure A                     Figure B
                        r red bead
                        b blue bead
                        w white bead
项链上的第一个和第二个珠子已经在图中标出了。

图 A 也可以用一个由 b 和 r 组成的字符串直接表示,b 代表蓝色而 r 代表红色,如下所示:brbrrrbbbrrrrrbrrbbrbbbbrrrrb。

假设你想从项链的某处将它截断拉直;接着从一端向另外一端数收集同颜色的珠子,直到碰到一个不同颜色的珠子为止;然后再从另外一端做同样的操作。(一端收集的珠子颜色可以不同于另一端的。)

请想办法找到一个截断项链的位置,能够让我们尽量多地收集到同色的珠子。

例子

如图 A 中的项链,从第 9 和第 10 个或者第 24 和 第 25 个珠子中间截断,则我们可以收集到 8 个珠子。

图 B 中的项链有白色的珠子,当遇到白色的珠子时,它既可以作为蓝色的珠子看待,也可以作为红色的珠子看待,由收集珠子时的需求决定。包含有白色珠子的项链则会由 r、b 和 w 字符组成的字符串来表示。

请编写一个程序计算从某条项链中能够收集到多少个珠子。

输入格式

第一行: N,项链上珠子的个数

第二行:一个字符串,长度为 N,由 r、b 和 w字符组成

输入样例

29 wwwbbrwrbrbrrbrbrwrwwrbwrwrrb

输出格式

输出一行字符,它应该包含了计算出的结果。

输出样例

11

2.算法:

首先对于动态规划的算法我们首先需要定义状态:
这里我们根据题目需要,需要定义两个状态
dp1[i]代表数组标号为i的元素左边的连续最大长度
dp2[i]代表数组标号为i的元素的右边的最大连续长度
    最终的结果,最大值应该是所有的dp1[i]+dp2[i+1]的最大值

定义状态转移方程:
if data[i]=data[i-1]  dp1[i]=dp1[i-1]+1
else  dp1[i]=1

if  data[i]=data[i+1]   dp2[i]=dp2[i+1]+1;
else dp2[i]=1

上述只是我们的思维展示,实际上的一些技巧也是必须的
1.复制数组空间2倍
2.控制最终的访问边界

3.AC核心代码:

为了防止网教查重,我只附上核心代码段:
dp1  (now控制访问边界)
for(int i=2+n;i<=2*n;i++)
	{
		if(j=='\0'||data[i]==j||data[i]=='w') 
		{
			dp[i-n]=dp[i-1-n]+1;
			if(data[i]!='w') now=i;
		}
		else 
		{
			dp[i-n]=i-now;
			now=i;
			j=data[i];
		}
	}
dp2
	for(int i=n-1;i>=1;i--)
	{
		if(j=='\0'||data[i]==j||data[i]=='w') 
		{
			dpk[i]=dpk[i+1]+1;
			if(data[i]!='w') now=i;
		}
		else 
		{
			dpk[i]=now-i;
			now=i;
			j=data[i];
		}
	}


最终合并的核心代码段;
for(int i=1;i<=n;i++)
	{
		int k;
		if(i==n) k=dp[i]+dpk[1];
		else k=dp[i]+dpk[i+1];
		sum=sum>k?sum:k;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值