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. ES6:字面量的增强写法

    以前对象字面量的写法: 属性的增强写法: ES6中可以写成: 方法的增强写法 ES6中可以写成: ~~~~~ END ~~~~~

  2. 吴裕雄 python 神经网络——TensorFlow 输入文件队列

    import tensorflow as tf def _int64_feature(value): return tf.train.Feature(int64_list=tf.train.Int64 ...

  3. tf.app.run()的作用

    tf.app.run() 如果你的代码中的入口函数不叫main(),而是一个其他名字的函数,如test(),则你应该这样写入口tf.app.run(test) 如果你的代码中的入口函数叫main(), ...

  4. Tomcat访问控制及站点部署(以WAR包形式上传)!(重点)

    访问控制 首先安装好jdk以及apache-tomcat并能访问tomcat网页 点击server status了解服务状态会报403的错误 第一步:修改user.xml配置文件 [root@loca ...

  5. Linux 命令中 find 和 xargs 命令的用法

    find 命令(一) find 命令主要作用是沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作.Linux 下 find 命令提供了相当多的查找条件,功能很强大,对应的学习难度也比较大. ...

  6. Solidity顺序编程

    1.事件 是合约和区块链通讯的一种机制.前端可以监听事件. 使用关键字event(参数);来申请 2.require指令: 使用require指令,使得函数在执行过程中,在不满足某些条件的时候抛出错误 ...

  7. C、C++ 不得宠,微软正开发新的编程语言!

    76 年迭代与更新,编程语言界,谁主沉浮? 在六百多种编程语言中,对于开发者而言,其主观印象中或只有几种主流的编程语言,如 Java.C.C++.C#.新贵 Python 等,而之所以它们能够成为主流 ...

  8. input、raw_input区别,运算符,运算优先级,多变赋值方式

    目录 1. Python2中的input.raw_input赋值方式和Python3中的input赋值方式的差别 2. 运算符 3. python运算符优先级 4. 格式化输出 5. 链式赋值 6. ...

  9. linux磁盘管理1-分区格式化挂载,swap,df,du,dd

    一些基础 硬盘接口类型 ide 早期家庭电脑 scsi 早期服务器 sata 目前家庭电脑 sas 目前服务器 raid卡--阵列卡 网卡绑定 ABI 应用程序与OS之间的底层接口 API 应用程序调 ...

  10. 【原】php中fastcgi和php-fpm是什么东西

    fastcgi 是一个与平台无关,与语言无关,任何语言只要按照它的接口来实现,就能实现自己语言的fastcgi能力和web server 通讯. PHP-CGI就是PHP实现的自带的FastCGI管理 ...