0 s, 1 s and ? Marks UVA - 11920 贪心

问题

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值