您的位置:首页 > 编程语言

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

2016-09-07 18:18 260 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: