Codeforces 792C

题意:给出一个由0到9数字构成的字符串,要求删去最少的数位,使得这个字符串代表的数能被3整除,同时要求不能有前导零,并且至少有一位(比如数字11,删去两个1后就没有数位了,所以不符合)。如果能够处理出符合要求的字符串,输出之,否则输出-1。

 

解题思路:(这种题如果让我比赛做肯定写不出来,,细节太多了,磕磕碰碰看着数据改了好几次才勉强过的)

  首先可以想到的就是,要使能被3整除,各数字位的和能被3整除即可。设各数字位和为sum,并且使sum%=3,那么sum就只能是1或者2(如果是0那么直接输出即可),接下来是处理方式:

  sum==1,那么我们可以删去一个模3等于1的数字位,或者删去两个模3等于2的数字位(这个很容易漏)。

  sum==2,可以删去一个模3等于2的数字位,或者删去两个模3等于1的数字位。

  确定了删除方法后,就是处理各不同方法下可能会有的前导零,并且计算它们删去的数字位数,选取最少的作为最终答案。

  处理前导零有大坑!

  1、最简单想到的无非是只删除一个数字位的情况下,如果该数字位是首位,那么后面跟随的0要全部删掉

  2、删除两位数字的情况下,如果其中一个是首位,那么从首位开始的连续零要删掉,如200233;还有!如果从首位开始一直到另一个删除位都是0,那么另一个删除位后面的连续0也要删掉,如20200333;还有!如果一个是首位,另一个是末位,那么至少要留一个0,如20002。

  3、所有的删除操作都注意不要把最后一个0都删掉了使得变成了一个空字符串。

  基本容易踩的坑就上面这些了。如果是比赛现场,这种题还是要尽可能提前把所有情况的想好,最糟糕的情况是,即使后面找到了bug,也不知道怎么改了。

  下面贴出我丑的不能看的代码,,大概哪天有心情了再重写一遍。?

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
const int N=1e5+10;
char s[N];
int sum;
bool del[N];
int main(){
    scanf("%s",s);
    int len=strlen(s);
    if(len==1){
        int tmp=s[0]-'0';
        if(tmp%3==0) puts(s);
        else puts("-1");
        return 0;
    }
    for(int i=0;i<len;i++)
        sum+=s[i]-'0';
    sum%=3;
    if(!sum){
        puts(s);
        return 0;
    }
    int cnt2=0;
    bool flag=false,flag2=false;
    //只删一个
    for(int i=len-1;i>=0;i--){
        if((s[i]-'0')%3==sum){
            if(i!=0){
                del[i]=true;
                flag=true;
                break;
            }else{
                if(s[i+1]!='0'){
                    del[i]=true;
                    flag=true;
                }else{
                    flag2=true;
                    cnt2=1;
                    while(s[cnt2]=='0'&&cnt2<len-1) cnt2++;
                }
            }
        }
    }
    //删两个,仅限于sum==2,找两个1
    if(!flag&&len>2){
        int cnt=0;
        int tar=sum==2?1:2;
        for(int i=len-1;i>0;i--){
            if((s[i]-'0')%3==tar){
                cnt++;
                del[i]=true;
                if(cnt==2) break;
            }
        }
        if(cnt==1){
            if((s[0]-'0')%3==tar){
                if(s[1]!='0'){
                    flag=true;
                    del[0]=true;
                    cnt++;
                    while(s[cnt]=='0'&&cnt<len-1) del[cnt++]=true;
                }else{
                    del[0]=true;
                    int tmp=1;
                    int lim=len-1;
                    //处理2002这种数据用的判断
                    while(del[lim]) lim--;
                    while(s[tmp]=='0'&&tmp<lim) del[tmp++]=true;
                    cnt+=tmp;
                    //处理202003这种数据
                    if(del[tmp]){
                        tmp++;
                        while(s[tmp]=='0'&&tmp<lim) del[tmp++]=true;
                        cnt=tmp;
                    }
                }
            }
        }
        if(cnt&&(cnt<=cnt2||!flag2)){
            for(int i=0;i<len;i++) if(!del[i]){
                putchar(s[i]);
            }
            puts("");
        }else{
            for(int i=cnt2;i<len;i++)
                putchar(s[i]);
            puts("");
        }
    }
    else{
        if(flag){
            for(int i=0;i<len;i++) if(!del[i]){
                putchar(s[i]);
            }
            puts("");
        }
        else if(flag2){
            for(int i=cnt2;i<len;i++)
                putchar(s[i]);
            puts("");
        }
        else puts("-1");
    }
    return 0;
}

 

posted @ 2017-03-28 16:12  轶辰  阅读(448)  评论(0编辑  收藏  举报