题目:

You have a necklace of N red, white, or blue beads (3<=N<=350) some of which are red, others blue, and others white, arranged at random. Here are two examples for 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

The beads considered first and second in the text that follows have been marked in the picture.

The configuration in Figure A may be represented as a string of b's and r's, where b represents a blue bead and r represents a red one, as follows: brbrrrbbbrrrrrbrrbbrbbbbrrrrb .

Suppose you are to break the necklace at some point, lay it out straight, and then collect beads of the same color from one end until you reach a bead of a different color, and do the same for the other end (which might not be of the same color as the beads collected before this).

Determine the point where the necklace should be broken so that the most number of beads can be collected.

Example

For example, for the necklace in Figure A, 8 beads can be collected, with the breaking point either between bead 9 and bead 10 or else between bead 24 and bead 25.

In some necklaces, white beads had been included as shown in Figure B above. When collecting beads, a white bead that is encountered may be treated as either red or blue and then painted with the desired color. The string that represents this configuration can include any of the three symbols r, b and w.

Write a program to determine the largest number of beads that can be collected from a supplied necklace.

这一道题做了一整天,更郁闷的是对完答案发现自己的方法太复杂了

我总是想着先把整个项链都染色成 red 或 blue 然后把每一段的相同颜色串的数量数出来 实际上可以每次只考虑一个缺口位置的局部信息就好了  不需要提前染色 也不需要将整个项链的所有相同颜色玻璃串的个数存起来 因为存起来后 对于rwb bwr的情况还是要单独分析

用到了一些小技巧:

1.环装一定会用到mod 不过一般都是数字超过了范围用模电 这个项链可能数到-1 、-2 需要自己定义一个新的有负数的mod 或者 把信息存储两遍这样 可以在第一遍存储的最后可以直接通过加法读取下一个存储的起始的玻璃珠信息

答案:思路最清楚的代码

#include <stdio.h>
#include <string.h>
#include <assert.h> #define MAXN 400 char necklace[MAXN];
int len; /*
* Return n mod m. The C % operator is not enough because
* its behavior is undefined on negative numbers.
*/
int
mod(int n, int m)
{
while(n < )
n += m;
return n%m;
} /*
* Calculate number of beads gotten by breaking
* before character p and going in direction dir,
* which is 1 for forward and -1 for backward.
*/
int
nbreak(int p, int dir)
{
char color;
int i, n; color = 'w'; /* Start at p if going forward, bead before if going backward */
if(dir > )
i = p;
else
i = mod(p-, len); /* We use "n<len" to cut off loops that go around the whole necklace */
for(n=; n<len; n++, i=mod(i+dir, len)) {
/* record which color we're going to collect */
if(color == 'w' && necklace[i] != 'w')
color = necklace[i]; /*
* If we've chosen a color and see a bead
* not white and not that color, stop
*/
if(color != 'w' && necklace[i] != 'w' && necklace[i] != color)
break;
}
return n;
} void
main(void)
{
FILE *fin, *fout;
int i, n, m; fin = fopen("beads.in", "r");
fout = fopen("beads.out", "w");
assert(fin != NULL && fout != NULL); fscanf(fin, "%d %s", &len, necklace);
assert(strlen(necklace) == len); m = ;
for(i=; i<len; i++) {
n = nbreak(i, ) + nbreak(i, -);
if(n > m)
m = n;
} /*
* If the whole necklace can be gotten with a good
* break, we'll sometimes count beads more than
* once. this can only happen when the whole necklace
* can be taken, when beads that can be grabbed from
* the right of the break can also be grabbed from the left.
*/
if(m > len)
m = len; fprintf(fout, "%d\n", m);
exit ();
}

动态规划的答案我没怎么看还:

#include <stdio.h>
#include <string.h>
#include <algorithm> using namespace std; FILE *in,*out; int main () {
in = fopen("beads.in", "r");
out = fopen ("beads.out", "w"); int n;
char tmp[], s[];
fscanf(in, "%d %s", &n, tmp); strcpy(s, tmp);
strcat(s, tmp); int left[][], right[][];
left[][] = left[][] = ; for (int i=; i<= * n; i++){
if (s[i - ] == 'r'){
left[i][] = left[i - ][] + ;
left[i][] = ;
} else if (s[i - ] == 'b'){
left[i][] = left[i - ][] + ;
left[i][] = ;
} else {
left[i][] = left[i - ][] + ;
left[i][] = left[i - ][] + ;
}
} right[ * n][] = right[ * n][] = ;
for (int i= * n - ; i >= ; i--){
if (s[i] == 'r'){
right[i][] = right[i + ][] + ;
right[i][] = ;
} else if (s[i] == 'b'){
right[i][] = right[i + ][] + ;
right[i][] = ;
} else {
right[i][] = right[i + ][] + ;
right[i][] = right[i + ][] + ;
}
} int m = ;
for (int i=; i< * n; i++)
m = max(m, max(left[i][], left[i][]) + max(right[i][], right[i][]));
m = min(m, n);
fprintf(out, "%d\n", m);
fclose(in); fclose(out);
return ;
}

简便的方案:

#include <iostream>
#include <fstream>
using namespace std; int main() {
fstream input, output;
string inputFilename = "beads.in", outputFilename = "beads.out";
input.open(inputFilename.c_str(), ios::in);
output.open(outputFilename.c_str(), ios::out); int n, max=, current, state, i, j;
string s;
char c; input >> n >> s;
s = s+s;
for(i=; i<n; i++) {
c = (char) s[i];
if(c == 'w')
state = ;
else
state = ;
j = i;
current = ;
while(state <= ) {
// dont go further in second string than starting position in first string
while(j<n+i && (s[j] == c || s[j] == 'w')) {
current++;
j++;
} // while
state++;
c = s[j];
} // while
if(current > max)
max = current;
} // for output << max << endl;
return ;
} // main

我自己写的非常复杂 但至少还对了的代码:

#include<stdio.h>
#include<string.h>
#include<assert.h> #define MaxLength 350
typedef struct{
int color;
int num;
int type;
} Pos; typedef struct {
int colorleft;
int colorright;
int location;
int length;
}RWB; typedef struct {
int num;
int type;
}NUM;
enum Type{left, right}; int main()
{
FILE *in, *out;
int num, longgest = ;
int countr = , countb = ;
int tmp;
int length = ;
int recordnum = , recorddnum = ;
int i = , j;
int first = -; //最小的记录点
char necklace[]; in = fopen("beads.in", "r");
out = fopen("beads.out", "w"); fscanf(in, "%d", &length);
fscanf(in, "%s", necklace); while(i < length) //得到项链长度
{
if(necklace[i] == 'r')
countr++;
else if(necklace[i] == 'b')
countb++;
i++;
} if(countr == || countb == )
{
fprintf(out ,"%d\n", length);
return ;
} Pos record[MaxLength];
RWB recordd[MaxLength];
i = ;
while(i < length) //定位第一个left
{
if(necklace[i] != 'w' && necklace[i+] == 'w')
{
first = i;
record[].color = necklace[i];
record[].num = i;
record[].type = left;
recordnum++;
break;
}
i++;
} if(first != -)
{
for(i = first + ; i != first; i = (i + ) % length) //记录 bw wb rw wr的位置
{
if(necklace[i] != 'w' && necklace[(i+)%length] == 'w')
{
record[recordnum].color = necklace[i];
record[recordnum].num = i;
record[recordnum].type = left;
recordnum++;
}
else if(necklace[i] == 'w' && necklace[(i+)%length] != 'w')
{
record[recordnum].color = necklace[(i+)%length];
record[recordnum].num = (i+)%length;
record[recordnum].type = right;
recordnum++;
}
} assert(recordnum % == );
assert(record[recordnum-].type == right); for(i = ; i < recordnum; i = i + ) //根据记录信息 将 rw...wr 和 bw...wb的直接染色 将 rw..wb bw..wr的取出
{
assert((record[i].type == left && record[i+].type == right));
if(record[i].color == record[i+].color)
{
for(j = (record[i].num + )%length; j != record[i+].num; j = (j + ) % length)
{
necklace[j] = record[i].color;
} }
else
{
recordd[recorddnum].colorleft = record[i].color;
recordd[recorddnum].colorright = record[i+].color;
recordd[recorddnum].length = record[i+].num - record[i].num - ;
recordd[recorddnum].location = record[i].num;
recorddnum++;
}
}
} //fprintf(out,"%s",necklace); NUM record2[MaxLength];
int record2num = ;
int numtmp = ;
for(i = ; i < length; i++) //统计项链相同颜色的个数 存放在数组中
{
if(necklace[i] == necklace[i+] )
{
numtmp++;
}
else
{
record2[record2num].num = numtmp;
if(necklace[i] == 'w')
record2[record2num].type = ;
else
record2[record2num].type = ;
numtmp = ;
record2num++;
}
}
if(necklace[] == necklace[length - ]) //处理最后颜色与第一个颜色相同
{
record2num--;
record2[].num += record2[record2num].num;
}
for(i = ; i < record2num; i++)
{
record2[record2num + i] = record2[i];
} int longgesttmp = ;
int n;
for(i = ; i < record2num ;i++) //根据存储的数组找最长链
{
n = ;
j = i;
longgesttmp = ;
while()
{
if(record2[j].type == )
n++;
if(n == && j % record2num == i && record2[j].type == )
break;
if(n<)
longgesttmp += record2[j].num;
else
break;
j++;
}
if(longgesttmp > longgest)
{
longgest = longgesttmp;
}
} fprintf(out , "%d\n", longgest); return ;
}

【USACO】beads的更多相关文章

  1. POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)

    POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...

  2. 1642: 【USACO】Payback(还债)

    1642: [USACO]Payback(还债) 时间限制: 1 Sec 内存限制: 64 MB 提交: 190 解决: 95 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 &quo ...

  3. 1519: 【USACO】超级书架

    1519: [USACO]超级书架 时间限制: 1 Sec 内存限制: 64 MB 提交: 1735 解决: 891 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 Farmer Jo ...

  4. Java实现【USACO】1.1.2 贪婪的礼物送礼者 Greedy Gift Givers

    [USACO]1.1.2 贪婪的礼物送礼者 Greedy Gift Givers 题目描述 对于一群要互送礼物的朋友,你要确定每个人送出的礼物比收到的多多少(and vice versa for th ...

  5. 【CPLUSOJ】【USACO】【差分约束】排队(layout)

    [题目描述] Robin喜欢将他的奶牛们排成一队.假设他有N头奶牛,编号为1至N.这些奶牛按照编号大小排列,并且由于它们都很想早点吃饭,于是就很可能出现多头奶牛挤在同一位置的情况(也就是说,如果我们认 ...

  6. 【USACO】Dining

    [题目链接] [JZXX]点击打开链接 [caioj]点击打开链接 [算法] 拆点+网络流 [代码] #include<bits/stdc++.h> using namespace std ...

  7. 【USACO】Optimal Milking

    题目链接 :        [POJ]点击打开链接        [caioj]点击打开链接 算法 : 1:跑一遍弗洛伊德,求出点与点之间的最短路径 2:二分答案,二分”最大值最小“ 3.1:建边,将 ...

  8. 【USACO】 Balanced Photo

    [题目链接] 点击打开链接 [算法] 树状数组 [代码] #include<bits/stdc++.h> using namespace std; int i,N,ans,l1,l2; ] ...

  9. 【USACO】 Balanced Lineup

    [题目链接] 点击打开链接 [算法] 这是一道经典的最值查询(RMQ)问题. 我们首先想到线段树.但有没有更快的方法呢?对于这类问题,我们可以用ST表(稀疏表)算法求解. 稀疏表算法.其实也是一种动态 ...

随机推荐

  1. 15.Android中LinearLayout布局一些小记录

    在App中,我们经常看到布局中会有分割线,直接上代码: <?xml version="1.0" encoding="utf-8"?> <Lin ...

  2. 状态压缩dp问题

    问题:Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Ev ...

  3. poj 1061 扩展欧几里得解同余方程(求最小非负整数解)

    题目可以转化成求关于t的同余方程的最小非负数解: x+m*t≡y+n*t (mod L) 该方程又可以转化成: k*L+(n-m)*t=x-y 利用扩展欧几里得可以解决这个问题: eg:对于方程ax+ ...

  4. hdu 3068 最长回文子串 TLE

    后缀数组+RMQ是O(nlogn)的,会TLE..... 标准解法好像是马拉车,O(n).... #include "algorithm" #include "cstdi ...

  5. [NOIP2008] 提高组 洛谷P1006 传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  6. c++内存分配(new和delete)

    c中malloc和free是函数,包含在stdlib.h头文件中,分配成功返回指针,失败返回空指针. 与new的区别是: 1,malloc与free是C++/C语言的标准库函数,new/delete是 ...

  7. linux java cpu 100%

    1.用top找到最耗资源的进程id [ bin]# toptop - 16:56:14 up 119 days, 6:17, 7 users, load average: 2.04, 2.07, 2. ...

  8. Bootstrap教程:[4]栅格系统详解

    http://jingyan.baidu.com/article/6f2f55a1852aa1b5b83e6c5a.html 们都知道bootstrap3.0使用了四种栅格选项来形成栅格系统,这四种选 ...

  9. nginx配置ssl双向验证 nginx https ssl证书配置

    1.安装nginx 参考<nginx安装>:http://www.ttlsa.com/nginx/nginx-install-on-linux/ 如果你想在单IP/服务器上配置多个http ...

  10. tp三大自动

    ThinkPHP三大自动 (2012-03-21 10:48:56) 转载▼ 标签: thinkphp 三大自动 自动验证 自动完成 自动填充 自动映射 字段映射 杂谈 分类: php 一.自动验证 ...