Broken Necklace-----破碎的项链----USACO---C1S1
来源:互联网 发布:linux cat 查看日志 编辑:程序博客网 时间:2024/06/02 14:57
在USACO中Chapter1,Section1的题目。记录以便日后查看。翻译及部分思路来自NOCOW。
题目的中文翻译为:
你有一条由 N 个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子:
第一和第二个珠子在图片中已经被作记号.
图片 A 中的项链可以用下面的字符串表示:
brbrrrbbbrrrrrbrrbbrbbbbrrrrb .
假如你要在一些点打破项链,展开成一条直线,然后从一端开始收集同颜色的珠子直到你遇到一个不同的颜色珠子,在另一端做同样的事.(颜色可能与在这之前收集的不同) 确定应该在哪里打破项链来收集到最大多数的数目的子. Example 举例来说,在图片 A 中的项链,可以收集到 8 个珠子,在珠子 9 和珠子 10 或珠子 24 和珠子 25 之间打断项链. 在一些项链中,包括白色的珠子如图片 B 所示. 当收集珠子的时候,一个被遇到的白色珠子可以被当做红色也可以被当做蓝色. 表现项链的字符串将会包括三符号 r , b 和 w . 写一
图片 A 中的项链可以用下面的字符串表示:
brbrrrbbbrrrrrbrrbbrbbbbrrrrb .
假如你要在一些点打破项链,展开成一条直线,然后从一端开始收集同颜色的珠子直到你遇到一个不同的颜色珠子,在另一端做同样的事.(颜色可能与在这之前收集的不同) 确定应该在哪里打破项链来收集到最大多数的数目的子. Example 举例来说,在图片 A 中的项链,可以收集到 8 个珠子,在珠子 9 和珠子 10 或珠子 24 和珠子 25 之间打断项链. 在一些项链中,包括白色的珠子如图片 B 所示. 当收集珠子的时候,一个被遇到的白色珠子可以被当做红色也可以被当做蓝色. 表现项链的字符串将会包括三符号 r , b 和 w . 写一
个程序来确定从一条被供应的项链最大可以被收集珠子数目.
问题解答:
可以把珠子想象成从第n个和第一个珠子之间断裂,此时项链变成了一个串,在此串上解决问题。
算法一:搜索法
从项链的第一个珠子算起,分别向两个方向搜索最长的连续字串,并记录最大值。算法的复杂度为O(N2)。
算法二:动态规划法
分别从两个方向搜索到项链的第i个珠子时,最长的字串。例如在第3个和第4个珠子之间断裂,先不考虑白色的珠子,则如下图:
可以看出,只要求出在第i个和第i+1个位置断裂时,截止到第i个珠子从右到左的最大字串长度和截止到第i+1个珠子时从左到有的最大字串长度即可。
先看从右到左时:
用一个数组保存最大字串的长度,记为R2L。则
R2L[i-1] + 1 第i-1个珠子和第i个珠子相同
R2L[i] =
1 第i-1个珠子和第i个珠子不相同
有了此公式便可以用动态规划求出从右到左时的最大字串长度。但是此时还有一个问题,之前我们把项链看成是从第n个位置和第1个位置之间裂开的,但是实际并不是这样,项链是一个环。此时 我们可以用两种方法解决。
第一种:
将项链看成两个串相连,例如从第一个到第4个分别为RRBB。我们把他看成
array = RRBB + RRBB。 (i=1....n)
按动态规划公式求出最长字串。并将array[3] 对应到R2L[3],array[4]对应到R2L[4],array[5]对应到R2L[1],array[6]对应到R2L[2]。即去前串的后半部分,后串的前半部分。
第二种:
先判断是否都为一个颜色的串,若是一个颜色的串,则R2L[i] = n。否则计算R2L[1...n]后,再判断珠子的第1个和第n个是否相同,若相同,再计算R2L[1...i]直到第i-1个珠子和第i个珠子不相同为止。
从左到右时,同理
R2L[i+1] + 1 第i+1个珠子和第i个珠子相同
L2R[i] =
1 第i+1个珠子和第i个珠子不相同
上面我们忽略了W珠子的存在,现在来考虑W珠子。由于W珠子可以当做蓝色或红色珠子,所以我们把W珠子按红色扫描一遍,再将W当做蓝色扫描一遍。并合并两次扫描的结果,取最大的结果。
之后就是扫描R2L和L2R数组,假设在第i和i+1位置之间断开,则计算R2L[i] + L2R[i+1],求出所有的和,取最大的即为结果。
算法的实现:
package chapt1.section1;public class P4 {/** * 根据array填充R2L * @param array * @param a R2L数组 * @param s 将W当做R或者B */public void fill(char[] array,int[] a,char s){int n = array.length;a[0] = 1;for(int i = 1 ; i < n ; i++){char ai = array[i]=='w' ? s : array[i];char ai1 = array[i-1] == 'w' ? s : array[i-1];if(ai == ai1)a[i] = a[i-1] + 1;elsea[i] = 1;}if(array[n-1] == 'w' || array[n-1] == s){a[0] = a[n-1] + 1;for(int i = 1; i < n ; i++){char ai = array[i]=='w' ? s : array[i];char ai1 = array[i-1] == 'w' ? s : array[i-1];if(ai == ai1)a[i] = a[i-1] + 1;elsebreak;}}}/** * 填充L2R * @param array * @param a L2R 数组 * @param s 将W当做R或B */public void fill2(char[] array,int[] a,char s){int n = array.length;a[n-1] = 1;for(int i = n-2 ; i >= 0 ; i--){char ai = array[i]=='w' ? s : array[i];char ai1 = array[i+1] == 'w' ? s : array[i+1];if(ai == ai1)a[i] = a[i+1] + 1;elsea[i] = 1;}if(array[0] == 'w' || array[0] == s){a[n-1] = a[0] + 1;for(int i = n-2 ; i >= 0 ; i--){char ai = array[i]=='w' ? s : array[i];char ai1 = array[i+1] == 'w' ? s : array[i+1];if(ai == ai1)a[i] = a[i+1] + 1;elsea[i] = 1;}}}/** * 取两个数组中最大的值放入a1中 * @param a1 * @param a2 */public void merge(int[] a1,int[] a2){for(int i = 0; i < a1.length ; i++){if(a2[i] > a1[i])a1[i] = a2[i];}}public void beads(char[] array){int n = array.length;int[] rcw = new int[n]; //R2L数组,将W当做R cw为clockwiseint[] bcw = new int[n]; //R2L数组,将W当做Bint[] bccw = new int[n]; //L2R数组,将W当做R ccw为counter clockwiseint[] rccw = new int[n]; //L2R数组,将W当做Bboolean flag[] = {false,false};//检查是否全部相同,即是否为RRRRRRRRRR或BBBBBB这样的串for(int i = 0; i < n ; i++){if(array[i] == 'r'){flag[0] = true;}if(array[i] == 'b'){flag[1] = true;}}if(flag[0] == false || flag[1] == false){//如果是,结果为nSystem.out.println(n);return;}else{//计算数组fill(array,rcw,'r');fill(array,bcw,'b');fill2(array,rccw,'r');fill2(array,bccw,'b');//合并merge(rcw,bcw);merge(rccw,bccw);//rcw rccwint sum = -1;for(int i = 0 ; i < n ; i++){if(i == n-1){if(sum < (rcw[i] + rccw[0]))sum = (rcw[i] + rccw[0]);}else{if(sum < (rcw[i] + rccw[i+1]))sum = (rcw[i] + rccw[i+1]);}}System.out.println(sum);}}public static void main(String[] args){String b = "wwwbbrwrbrbrrbrbrwrwwrbwrwrrr";new P4().beads(b.toCharArray());} }
0 0
- Broken Necklace-----破碎的项链----USACO---C1S1
- Broken Necklace破碎的项链
- Broken Necklace破碎的项链
- Usaco 1.1.4 破碎的项链(Broken Necklace)
- 【USACO题库】1.1.4 Broken Necklace破碎的项链
- 【USACO题库】1.1.4 Broken Necklace破碎的项链
- 【USACO题库】1.1.4 Broken Necklace破碎的项链
- usaco1.1.4 Broken Necklace破碎的项链
- USACO1.1.4 Broken Necklace(破碎的项链)
- USACO1.1.4 Broken Necklace 破碎的项链
- 【USACO1.1_4】★Broken Necklace 破碎的项链
- broken necklaces破碎的项链
- USACO——Broken Necklace 坏掉的项链
- Broken Necklace 坏掉的项链
- [USACO1.1.4]坏掉的项链Broken Necklace
- USACO Section1.2破碎的项链
- USACO 1.1 破碎的项链
- USACO 1.1 破碎的项链(模拟)
- 求数列的下一个排列
- 关于error LNK:2019错误的札记
- 在actionbar的PopupWindow
- 打造自己的字节序转换函数(16位、32位和64位)
- 酷派手机出货量创历史新高 单月超600万台
- Broken Necklace-----破碎的项链----USACO---C1S1
- android 国际化EditText空格问题
- 通用字节序转换函数
- 旋转卡壳法求最大三角形
- hdu 1503 最长公共子序列
- 巧用QSignalMapper分类有序地处理大量信号
- 1.3.线程基础_等待线程
- 阿里巴巴集团2013年净利润达35.61亿美元
- 自定义UICollectionViewLayout并添加UIDynamic