题意:
给一个项链(首尾相连),从某个地方断开,然后两头取相同的珠子,问最多能取多少个
有三种珠子:r,w,b。其中w是百变珠子,可以当成w或者r。
类型:
模拟
思路:
首先,断开的地方不会是某个连续串的中间(因为,断开在中间比断开在两头非但不会得到更好的结果,反而可能得到更差的结果)
其次,bw..wb = b..b rw..wr = r..r
整个程序的思路就是
先压缩字符串(把相同的合并)
然后处理第二个条件
再次压缩,得到最终串
然后枚举每个地方,模拟人去取,看能取多少个
(关键是考虑好各种特殊情况。。。。恶心啊)
代码:
/* PROG: beads LANG: C++ */ /************************************************************************* > File Name: usaco1-1-beads.cpp > Author: Shine > Created Time: 2013-05-20 下午 12:39:47 > QuestionType: 模拟 > Way: 模拟 > Submit: 3WA 1A > Gain: 小心模拟 > Experience: 小心模拟 ************************************************************************/ //b???b => bbbbb //a???a => aaaaa //a???b //wwwbbrwrbrbrrbrbrwrwwrbwrwrrb //bbbbbrrrbrbrrbrbrrrrrrbwrrrrb //brbrbrbrbrbwr //6311121116114 //左右找两个。如果两个之中有w,则加,否则取最近一个 // //特例: //bbb //b //3 #include <cstdio> #include <cstring> int n; char str[1000]; void Compress(char str[],int nu[]){ //把多个连续字符压缩成单个字符 int i; int n = strlen(str); char compress[1000]; int num[1000]; int p = 0; //找连续串的最后一个字符 for (i = 0; i < n && str[i] != -1; i++) { //str[i] == -1说明被删除了,然而删除就是连续的,说明前面都被删除了 if (str[i] != str[(i+1)%n]) { int k; compress[p] = str[i]; num[p] = nu[i]; for (k = (i-1+n)%n; k != i; k = (k-1+n)%n) {//向前搜索 if (str[k] == compress[p]) { num[p] += nu[k]; str[k] = -1; } else { p++; break; } } } } //特殊情况:整个串都连续…… if (p == 0) { compress[p] = str[0]; num[p] = 0; int len = strlen(str); int k; for (k = 0; k < len; k++) { num[p] += nu[k]; } p++; } compress[p] = 0; for (i = 0; compress[i]; i++) { str[i] = compress[i]; nu[i] = num[i]; } str[i] = 0; //puts(compress); //for (i = 0; i < p; i++) { // printf("%d", num[i]); //}puts(""); } int main() { freopen("beads.in", "r",stdin); freopen("beads.out", "w", stdout); scanf("%d", &n); scanf("%s", str); int i; int ans = 0; int num[1000]; for (i = 0; i < 1000; i++) { num[i] = 1; } Compress(str, num); //puts(str); int len = strlen(str); for (i = 0; i < len; i++) { if (str[i] == 'w' && str[(i-1+len)%len] == str[(i+1)%len]) { str[i] = str[(i+1)%len]; } } //puts(str); Compress(str, num); len = strlen(str); for (i = 0; i < len; i++) { int tmpans = 0; int vis[1000] = {0}; int k; int pickn = 0; //printf("i = %d\n", i); for (k = i; str[k] == 'w' && k != (i-1+len)%len; k = (k+1)%len); char good = str[k]; //printf("->good = %c\n", good); for (k = i; pickn < len; k = (k+1)%len) { if (str[k] == good || str[k] == 'w') { if (!vis[k]) { vis[k] = 1; pickn++; tmpans += num[k]; } else break; } else break; } for (k = (i-1+len)%len; str[k] == 'w' && k != i; k = (k-1+len)%len); good = str[k]; //printf("<-good = %c\n", good); for (k = (i-1+len)%len; pickn < len; k = (k-1+len)%len) { if (str[k] == good ||str[k] == 'w') { if (!vis[k]) { vis[k] = 1; pickn++; tmpans += num[k]; }else break; } else break; } if (ans < tmpans) ans = tmpans; } printf("%d\n", ans); return 0; }