Solution

这道题数据规模奇小,因此大部分人都使用了暴力搜索的方法,这也是我一开始的想法。

对于 100100%100 的数据,3≤n≤3503≤n≤3503≤n≤350

的确可以如此,但暴力搜索的方法也需要进行一些奇怪的判断,因此我又决定直接打dp的解法,其实dp也是很自然的一种想法……

Dynamic Programming

我们可以发现,每个点向左向右,取蓝色取红色能连续取的个数一定是确定的。

于是我们定义dp数组:

int lr[maxn];
//lr[i]代表从i点向左不取i点
//即在 [1,i-1] 范围内从i-1开始能连续取多少个红色珠子
int lb[maxn];
//lb[i]代表从i点向左不取i点
//即在 [1,i-1] 范围内从i-1开始能连续取多少个蓝色珠子
int rr[maxn];
//rr[i]代表从i点向右取i点
//即在[i,n] 范围内从i开始能连续取多少个红色珠子
int rb[maxn];
//rb[i]代表从i点向右取i点
//即在[i,n] 范围内从i开始能连续取多少个蓝色珠子

那么在一个点断开,能取得的珠子个数就是:

ans[i]=max(lr[i],lb[i])+max(rr[i],rb[i])ans[i] = max(lr[i],lb[i]) + max(rr[i],rb[i])ans[i]=max(lr[i],lb[i])+max(rr[i],rb[i])

相信转移方程非常自然吧,我们先考虑向左取的情况:

  1. 前一个点为白色,那么有:

    lr[i]=lr[i−1]+1lr[i] = lr[i-1] + 1lr[i]=lr[i−1]+1

    lb[i]=lb[i−1]+1lb[i] = lb[i-1] + 1lb[i]=lb[i−1]+1
  2. 前一个点为红色,那么有:

    lr[i]=lr[i−1]+1lr[i] = lr[i-1] + 1lr[i]=lr[i−1]+1

    lb[i]=0lb[i] = 0lb[i]=0
  3. 前一个点为蓝色,那么有:

    lr[i]=0lr[i] = 0lr[i]=0

    lb[i]=lb[i−1]+1lb[i] = lb[i-1] + 1lb[i]=lb[i−1]+1

为什么考虑前一个点呢?

因为lr[i]lr[i]lr[i]和lb[i]lb[i]lb[i]代表的是区间[1,i−1][1,i-1][1,i−1]内从点i−1i-1i−1开始取能连续取多少,因此实际考虑的是点i−1i-1i−1的颜色。

向右的情况也是同理,有:

  1. 当前点为白色,那么有:

    rr[i]=rr[i+1]+1rr[i] = rr[i+1] + 1rr[i]=rr[i+1]+1

    rb[i]=rb[i+1]+1rb[i] = rb[i+1] + 1rb[i]=rb[i+1]+1
  2. 当前点为红色,那么有:

    rr[i]=rr[i+1]+1rr[i] = rr[i+1] + 1rr[i]=rr[i+1]+1

    rb[i]=0rb[i] = 0rb[i]=0
  3. 当前点为蓝色,那么有:

    rr[i]=0rr[i] = 0rr[i]=0

    rb[i]=rb[i+1]+1rb[i] = rb[i+1] + 1rb[i]=rb[i+1]+1

    实现也很简单:
for (int i = 2; i <= n; ++i)
{
if (s[i - 1] == 'w')
lb[i] = lb[i - 1] + 1, lr[i] = lr[i - 1] + 1;
else if (s[i - 1] == 'b')
lb[i] = lb[i - 1] + 1, lr[i] = 0;
else
lb[i] = 0, lr[i] = lr[i - 1] + 1;
}
for (int i = n - 1; i; --i)
{
if (s[i] == 'w')
rb[i] = rb[i + 1] + 1, rr[i] = rr[i + 1] + 1;
else if (s[i] == 'b')
rb[i] = rb[i + 1] + 1, rr[i] = 0;
else
rb[i] = 0, rr[i] = rr[i + 1] + 1;
}

Finally

于是我们处理出了每个点向左向右取红取蓝最多能连续取多少个珠子。

那么从i−1i-1i−1点,向左最多能取多少呢?

left[i−1]=max(lr[i],lb[i])left[i-1] = max(lr[i],lb[i])left[i−1]=max(lr[i],lb[i])

从iii点,向右最多能取

right[i]=max(rr[i],rb[i])right[i] = max(rr[i],rb[i])right[i]=max(rr[i],rb[i])

假定我们断开i−1i-1i−1和iii,那么答案就是:

ans=left[i−1]+right[i]ans = left[i-1] + right[i]ans=left[i−1]+right[i]



ans=max(lr[i],lb[i])+max(rr[i],rb[i])ans = max(lr[i],lb[i]) + max(rr[i],rb[i])ans=max(lr[i],lb[i])+max(rr[i],rb[i])

最后扫一遍统计答案即可。

int ans = 0;
for (int i = 1; i <= n; ++i)
ans = max(ans, max(lb[i], lr[i]) + max(rb[i], rr[i]));

当然,还要注意答案不能超过原始的长度。

Code

拆环为链等细节就不赘述了。

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 710;
char s[maxn];
int n,lb[maxn], lr[maxn], rb[maxn], rr[maxn];
inline int max(const int &a, const int &b) { return a > b ? a : b; }
int main()
{
scanf("%d%s", &n, s + 1);
memcpy(s + n + 1, s + 1, n);
n <<= 1;
for (int i = 2; i <= n; ++i)
{
if (s[i - 1] == 'w')
lb[i] = lb[i - 1] + 1, lr[i] = lr[i - 1] + 1;
else if (s[i - 1] == 'b')
lb[i] = lb[i - 1] + 1, lr[i] = 0;
else
lb[i] = 0, lr[i] = lr[i - 1] + 1;
}
for (int i = n - 1; i; --i)
{
if (s[i] == 'w')
rb[i] = rb[i + 1] + 1, rr[i] = rr[i + 1] + 1;
else if (s[i] == 'b')
rb[i] = rb[i + 1] + 1, rr[i] = 0;
else
rb[i] = 0, rr[i] = rr[i + 1] + 1;
}
int ans = 0;
for (int i = 1; i <= n; ++i)
ans = max(ans, max(lb[i], lr[i]) + max(rb[i], rr[i]));
if (ans > n >> 1)
ans = n >> 1;
printf("%d\n", ans);
return 0;
}

[LuoguP1203][USACO1.1]P1203 Broken Necklace的更多相关文章

  1. 【USACO1.1】Broken Necklace

    题意 一个环形项链,有rbw三种珠子,r代表red,b代表blue,w代表white,从任意一个位置断开,两端分别取珠子,同一端取的珠子要相同颜色,w可以染成想要的颜色,即既可当作r也可以当作b,求最 ...

  2. P1203 [USACO1.1]坏掉的项链Broken Necklace

    P1203 [USACO1.1]坏掉的项链Broken Necklace不错的断环为链的模拟题,开成三倍,有很多细节要考虑,比如总长度要<=n,开头第一个是w等等. #include<bi ...

  3. 【P1203】 【USACO1.1】坏掉的项链Broken Necklace

    P1203 [USACO1.1]坏掉的项链Broken Necklace 题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 ...

  4. P1203 [USACO1.1]Broken Necklace(模拟-枚举)

    P1203 [USACO1.1]坏掉的项链Broken Necklace 题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 ...

  5. 题解 P1203 【[USACO1.1]坏掉的项链Broken Necklace】

    [USACO1.1]坏掉的项链Broken Necklace 22892 破碎的项链 方法一:很容易想到枚举断点,再分别两头找,但是要注意很多细节 #include<iostream> # ...

  6. 洛谷 P1203 [USACO1.1]坏掉的项链Broken Necklace

    坏掉的项链Broken Necklace 难度:★ Code: #include <iostream> #include <cstdio> #include <cstri ...

  7. [USACO1.1.4]坏掉的项链Broken Necklace

    P1203 [USACO1.1]坏掉的项链Broken Necklace 标签 搜索/枚举 USACO 难度 普及- 题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N&l ...

  8. 洛谷P1203 [USACO1.1]坏掉的项链Broken Necklace

    题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子: 第一和第二个珠子在图片中已经被作记号. 图片 A ...

  9. AC日记——[USACO1.1]坏掉的项链Broken Necklace 洛谷 P1203

    题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子: 第一和第二个珠子在图片中已经被作记号. 图片 A ...

随机推荐

  1. 【代码总结】GD库中简单的验证码

    大体思路: 代码部分: <?php //1.创建画布 $img = imagecreatetruecolor(100,30); //2.设置颜色 值越小,颜色越深 $color1 = image ...

  2. JavaScript相关

    用文本编辑软件和浏览器就能开发和调试JavaScript代码 Node.js  在浏览器之外(服务器端)独立运行Ja¬vaScript代码的Node.js于2009年问世,一个独立的JavaScrip ...

  3. [ DLPytorch ] 文本预处理&语言模型&循环神经网络基础

    文本预处理 实现步骤(处理语言模型数据集距离) 文本预处理的实现步骤 读入文本:读入zip / txt 等数据集 with zipfile.ZipFile('./jaychou_lyrics.txt. ...

  4. win10 免安装版本的MySQL的下载安装和配置

    一.概述 网上找了好多,发现好多不是linux系统的就是与现在新版本有出入,自己做小项目亲手实践了一下,供大家借鉴. MySQL版本:mysql-5.7.17 下载方法: 1.MySQL官方网址htt ...

  5. ubuntu13.10安装tomcat

    步骤: ubuntu :13.10(32bit) -->i586 jdk 1.7 安装JDK 步骤: 1.官网下载如下图: 2.点击java SE7,下载jdk1.7 3.点击接受,并下载对应的 ...

  6. 十八 OGNL特殊符号的作用,#,%,$

    主要有哪些字符? #:获取Context的数据,构建map %: 强制解析OGNL,强制不解析OGNL $ : 在配置文件中(xml,属性文件(国际化))使用OGNL #的用法: <body&g ...

  7. java 依赖注入

    https://blog.csdn.net/coderder/article/details/51897721 前言 在软件工程领域,依赖注入(Dependency Injection)是用于实现控制 ...

  8. 凭什么相信 5G 很安全?

    导读 电信行业及其专家指责科学家说,他们研究的5G无线技术所带来的手机辐射制造了恐慌.由于我们的许多研究工作都是由公共资助的,因此我们相信从道德的角度来看,我们有责任告知公众,经过同行评审的科学文献究 ...

  9. STM32 RTC上的唤醒和闹钟

    RTC很简单只要给备用电,RTC就会不停,可以进行设置和读时间.同时在RTC上也涉及了闹钟(EXTI_17:RTC_FLAG_ALRAF,相当于RTC的定时器,闹钟到了之后进行异步操作)和唤醒中断(低 ...

  10. 「CF1303C Perfect Keyboard」

    前置芝士 图的遍历:通过DFS或者BFS遍历全图. 前向星:用来存边,但是在本题用也可以用一个二维数组解决. 具体做法 先从判断YES和NO开始,可以发现如果一个字母与三个及以上不同的字母相邻时肯定是 ...