zoukankan      html  css  js  c++  java
  • 【t005】数字构造问题

    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;
    }
    
  • 相关阅读:
    HDU2027 统计元音 一点点哈希思想
    湖南工业大学第一届ACM竞赛 数字游戏 字符串处理
    湖南工业大学第一届ACM竞赛 我素故我在 DFS
    HDU3293sort
    HDU2082 找单词 母函数
    HDU1018 Big Number 斯特林公式
    湖南工业大学第一届ACM竞赛 分糖果 位操作
    UVA 357 Let Me Count The Ways
    UVA 147 Dollars
    UVA 348 Optimal Array Multiplication Sequence
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626669.html
Copyright © 2011-2022 走看看