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. BinaryTree(二叉树) - 再谈二叉树

    经过两天的研究,总算是完全梳理清二叉树的基本操作了,然后我又发现了一些对二叉树的新的认识. 先具体说说删除操作,前面在对二叉树的补充中,我说到了二叉树的删除操作可以有两种不同的代码编写方式(可点这里去 ...

  2. day04-MyBatis的缓存与懒加载

    为什么会用到缓存? 为了减少与数据库链接所消耗的时间,将查询到的内容放到内存中去,下次查询直接取用就ok了. 缓存的适应场景: 1.经常查询并且不经常改变的. 2.数据的正确与否对最终结果影响不大的. ...

  3. stack的使用-Hdu 1062

    Text Reverse Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  4. vmware fusion nat网络模式设置固定ip

    最近想在本地用虚拟环境搭一个k8s环境,但是发现虚拟机的ip会不定时自动变化,导致mosh客户端连接经常中断.于是就想让虚拟机的ip固定住,不再变动. mac 上的 vmware fusion 设置固 ...

  5. 使用KVC键值编码

    掌握KVC从不使用setter.getter.点语法开始. ----- 前言 对象的内部状态是由属性进行封装的.访问对象属性的方式平时在开发过程中用得最多的是getter方法和点语法.键值编程KVC也 ...

  6. Vue.js项目的开发环境搭建与运行

    写作背景:手上入一个用Vue框架写的微信公众号项目,根据公司安排,我负责项目源代码的验收工作(当然专业的工作检测会交给web开发人员,我只是想运行起来看一看). 1 开发环境安装步骤: (一)安装no ...

  7. 基于贝叶斯模型和KNN模型分别对手写体数字进行识别

    首先,我们准备了0~9的训练集和测试集,这些手写体全部经过像素转换,用0,1表示,有颜色的区域为0,没有颜色的区域为1.实现代码如下: # 图片处理 # 先将所有图片转为固定宽高,比如32*,然后再进 ...

  8. 15条MySQL改善经验让系统更稳定

    MySQL 作为目前的主流开源数据库, 既能挑战 “双11”,又能扛起 “618”,比起网红版数据库,MySQL 绝对是实力担当. 1. 为查询缓存优化查询 像 NOW() 和 RAND() 或是其它 ...

  9. Docker示例命令

    1.docker run -t -i -v /root/workspace/node:/home/exam:rw docker.io/node bin/sh    -t 给容器挂载一个伪终端    - ...

  10. List转为字符串

    2019-12-12 20:34:16 方法1: 转换后的格式为:"('111','112','1113')" List list = new ArrayList<>( ...