问题
https://vjudge.net/problem/UVA-11920
分析
一开始想到了贪心和迭代加深搜索,迭代加深搜索会超时。
贪心如何贪?
有两个方面要考虑
一个是连续的?的个数,另一个是左边和右边的字符相同还是不同
如果左右两边相同:
(1)如果有奇数个,那么就按照111 01010(???) 111 ,
这样交叉着排放,同样不会影响结果
(2)如果有偶数个,那么还是交叉着,111 010010(???) 111,这样排序,会增加一个长度是2的段
如果左右两边不同:
(1)如果是奇数个,那么 1111 01101(???) 000,如果奇数为1,那么一定会使一段变长,例如11111?00000,不管变为0,还是1,都会改变长度如果奇数大于1,那么就可以按照从两边到中间逐位取反的方式,中间随便,那么只有中间有个长度为2的组,两边长度不变
(2)如果是偶数个,按照从两边到中间逐位取反的方式,不影响结果
1111 0101(???) 0000000
注意:要便计算边填充
1
0000?111?0000
参考:https://blog.csdn.net/accelerator_/article/details/18219915
代码写得还是太烂了,直接用一个二元组保存组这一个信息,然后更新组的大小就好了,因为是顺序访问的,组也可以顺序访问。可读性和逻辑就好很多。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=1000+5,Inf=0x3f3f3f3f;
int n,kase=0,T;
char str[maxn];
inline int cnt(int start,int d){
int len=0;
char ch=str[start];
while(str[start]==ch){
start+=d;
++len;
}
return len;
}
int main(void){
// freopen("../Ch01_ex/UVA11920_in.txt","r",stdin);
// freopen("../Ch01_ex/UVA11920_out.txt","w",stdout);
scanf("%d",&T);
while(kase<T){
str[0]='\0';
scanf(" %s",str+1);
n=strlen(str+1)+1;
int ans=1;
for(int i=1;i<n;){
//非?的直接数
if(str[i]!='?'){
int len=cnt(i,1);
ans=max(ans,len);
i+=len;
continue;
}
int nl=0,nr=0,nm=0;
nm=cnt(i,1);
//如果是在两边的那就直接continue,不在两边的数左边的,右边的nl,nr
if(i>1 && i+nm<n) {
//不变的情况
if((str[i-1]==str[i+nm] && (nm&1)) || (str[i-1]!=str[i+nm] && (nm&1)==0)){
i+=nm;
continue;
}
nl=cnt(i-1,-1);
nr=cnt(i+nm,1);
}else {
i+=nm; continue;
}
if(nm&1){
if(nm==1){
if(nl==nr){str[i]=str[i-1]; ans=max(ans,nl+1);}
else { str[i]=(nl<nr)?str[i-1]:str[i+nm]; ans=max(ans,max(nl,nr));}
}else{
ans=max(ans,max(2,max(nl,nr)));
}
}else ans=max(ans,2);
i+=nm;
}
printf("Case %d: %d\n",++kase,ans);
}
return 0;
}