【t005】数字构造问题

来源:互联网 发布:mac版qq与win版啥区别 编辑:程序博客网 时间:2024/05/11 15:59

Time Limit: 1 second
Memory Limit: 50 MB

【问题描述】

给定一个只包含数字[0..9]的字符串,请使用字符串中的某些字符,构建一个能够整除15最大的整数。注意,字符串中的每个字符只能使用一次。 任务:求由给定字符串构造的能够整除15的最大整数

【输入】

共1行;输入数据为一个只包含数字[0..9]字符串,字符串的长度为1..1000。如果无法构建出该数字,请输出“impossible”。 

【输出】

输出一行数字串,表示能够整除15的最大整数。

【输入样例】

02041

【输出样例1】

4200

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t005

【题解】

/*    一个数字能被15整除;    则这个数的各个位上的数字的和是3的倍数;    末尾数字是0或5.    把所有的数字从大到小排序;    所有数字的和模3的结果;    1.如果为0        如果数字里面有0,则排序后0在最后面,则直接输出;        如果数字里面没有0,但是有5,则把1个5放在最后面;然后输出;        else            put("Impossible");    2.如果为1        则如果有余数为1的数字,选那个最小的,删掉它;        如果没有余数为1的数字,找两个余数为2的数字;        {            如果有0,则直接找两个最小的,删掉            如果没有0,则要考虑            是不是减掉一个5之后,还能找到两个余数为2的数字;                能则删掉;        }        是否删掉了数字使得所有数字的和%3==0?        是则根据有没有5和0,输出相应的答案;        否则无解;    2.如果为2        则如果有1个余数为2的数字;        {            如果有0,则直接找最小的那个删掉;            如果没有0,则要考虑            是不是减掉一个5之后,还能找到一个余数为2的数字;                能则删掉那个数字,否则"去找两个余数为1的数字",删掉;        }        没有        则去找两个余数为1的数字;            如果有就删掉最小的两个;        是否删掉了数字使得所有数字的和%3==0?        是则根据有没有5和0,输出相应的答案;        否则无解;*/


【完整代码】

#include <cstdio>#include <string>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 1000+100;string s;int bo[3];int a[MAXN],n,num = 0,t5 = 0,t0 = 0;bool ok1;bool cmp(int x,int y){    return x > y;}void find5(){    for (int i = 1;i <= n;i++)        if (a[i]==5)            {                a[i]=-1;                a[n+1] = 5;                break;            }}void output(){    int l = 1,r = n+1;    while (a[l]==0 || a[l]==-1) l++;    if (l>r)        puts("0");    for (int i = l;i <= n+1;i++)        if (a[i]!=-1)            printf("%d",a[i]);}void pd(){    if (ok1)//如果删掉数了    {        if (t0)//有0就直接输出        {            output();            exit(0);        }        if (t5)//执行这一段就表示没0,则如果有5就把5移到最后输出        {            find5();            output();            exit(0);        }    }    //没完成删数或没有0和5就输出无解    puts("impossible");}int main(){    //freopen("F:\\rush.txt","r",stdin);    cin >> s;    n = s.size();    for (int i = 0;i <= n-1;i++)        {            a[i+1] = s[i]-'0';            bo[a[i+1]%3]++;            num+=a[i+1];            if (a[i+1]==5) t5++;            if (a[i+1]==0) t0++;        }    sort(a+1,a+1+n,cmp);    a[n+1] = -1;    int x = num%3;    if (x==0)    {        if (t0)        {            for (int i = 1;i <= n;i++)                printf("%d",a[i]);            return 0;        }        if (t5)        {            find5();            for (int i = 1;i <= n+1;i++)                if (a[i]!=-1)                    printf("%d",a[i]);            return 0;        }        puts("impossible");        return 0;    }    if (x==1)    {        ok1 = false;        if (bo[1])        {            for (int i = n;i >= 1;i--)                if (a[i]%3==1)                {                    a[i] = -1;                    break;                }            ok1 = true;        }        if (!ok1 && bo[2]>=2)        {            if (t0>0)//直接找两个余数为2的删掉(最小)            {                int cnt = 0;                for (int i = n;i >= 1;i--)                    if (a[i]%3==2)                    {                        cnt++;                        a[i] = -1;                        if (cnt==2)                            break;                    }                ok1 = true;            }            //如果没有0,则还需要一个5            //看一下删掉一个5(所以你得先有一个5)            //之后还有没有两个余数为2的)->所以bo[2]>=3是条件            if (!ok1 && t5 && bo[2]>=3)            {                //如果5只有一个,就不能选5                bool ban5 = false;                int cnt = 0;                if (t5==1)                    ban5 = true;                for (int i = n;i>=1;i--)                    if (a[i]%3==2)                    {                        if (ban5)                            if (a[i]==5)                                continue;                        a[i] = -1;                        cnt++;                        if (cnt==2)                            break;                    }                ok1 = true;            }        }        //删数完成,根据0和5的个数判断输出        pd();    }    if (x==2)    {        ok1 = false;        if (bo[2])        {            if (t0)            {                for (int i = n;i>=1;i--)                    if (a[i]%3==2)                    {                        a[i] = -1;                        break;                    }                ok1 = true;            }            //如果下面这段执行是肯定没有0了            //则肯定要有一个5,减去5会让bo[2]--,所以bo[2]要大于1            if (!ok1 && t5 && bo[2]>1)            {                bool ban5 = false;                if (t5==1)                    ban5 = true;                for (int i = n;i >= 1;i--)                    if (a[i]%3==2)                    {                        if (ban5)                            if (a[i]==5)                                continue;                        a[i] = -1;                        break;                    }                ok1 = true;            }        }        if (!ok1 && bo[1]>=2)        {            int cnt = 0;            for (int i = n;i >= 1;i--)                if (a[i]%3==1)                {                    a[i] = -1;                    cnt++;                    if (cnt==2)                        break;                }            ok1 = true;        }        pd();    }    return 0;}
0 0