题一 电子数字

  1. 云栖社区>
  2. 博客列表>
  3. 正文

题一 电子数字

this_is_bill 2016-03-19 14:35:00 浏览746 评论0

摘要: 一、题目 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 电子数字在生活中很常见,而许多的电子数字是由LED数码管制作而成。数字LED数码管一般由7个发光二极管封装在一起,组成’8’字型,引线在内部连接完成。

一、题目

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

电子数字在生活中很常见,而许多的电子数字是由LED数码管制作而成。数字LED数码管一般由7个发光二极管封装在一起,组成’8’字型,引线在内部连接完成。如下图所示,我们可以对每个发光管进行编码从1到7。而数字0到数字9可以由这七根发光管的亮暗来表示。

这里写图片描述

对LED数码管的二极管进行编码

digit.jpg

用LED数码管表示数字0-9

假设我们现在有从左到右排列好的K个LED数码管,并且我们已知每个数码管当前有哪些编号的二极管是亮着的,另外剩余的二极管由于某些原因,我们并不清楚它们的亮暗情况。由于已经有部分二极管是确定亮着的,所以每个LED数码管能表示的数字范围会有所缩小,譬如假设1号二极管已经确定是亮着的状态,那么这个LED数码管就不能表示数字1和4。

我们想知道的是,给定一个数N,在这K个LED数码管的当前亮暗的状态下,所有可能表示的数中,比N小的数有多少个。

注意,前导0是必须的,假设有4个数码管的话,’0000’表示0,’0123’表示123,即每个数的表示方法唯一。

输入

每个输入数据包含多个测试点。

第一行为测试点的个数 S ≤ 100。之后是 S 个测试点的数据。测试点之间无空行。

每个测试点的第一行为 K(1 ≤ K ≤ 5)和N(0 ≤ N ≤ 109)。之后是K行,每行表示对应数码管已点亮的二极管的情况。每行至少包含一个数字,表示对应点亮的二极管的编号,即每个数码管至少有一根二极管是点亮的。二极管编号的范围保证在1到7之间,且每行无重复编号。

注意表示数码管点亮情况的每行数字之间以及行首行末之间可能存在冗余空格,每行的字符总长度不超过100。

输出

对于每个测试点,对应的结果输出一行,表示这K个数码管在当前状态下,所有可能表示的数中,比N小的数有多少个。

样例解释

第一个样例中,只有’020’, ‘026’, ‘028’符合要求。

第三个样例中,只有’000’符合要求。

样例输入

3
3 50
3 1
1 4 5
1 5 6 7
4 100
1 2 3
4 5
6
7
1 1
7

样例输出

3
0
1

分析:这题是一道相对思路直观的题目,但是后面处理比 N 小的数,是可以转换为排列组合的数学问题解的。当然这样就需要判断是不是相等,如果相等就继续深入。

二、code

排列法:

#include <iostream>
#include <string>
#include <math.h>

using namespace std;

int res[12][12];
int digitCnt[6] ={0}; //该位可行计数
int miniCnt[6] = {0}; //该位比之小的
int equalCnt[6] = {0}; //是否和所比数当位有相等

int manyDigit(int a) {

    int cnt = 1;
    while ( a/=10 ) {
        ++cnt;
    }

    return cnt;
}

//get特定位数
int getDigit(int a, int n) {

    int p = pow(10,n-1);
    return (a/p)%10;
}

void work(int &resCnt,int deep,int n) {

    if(deep == n) { //递归结束条件
        return;
    }

    if ( equalCnt[deep] ) { //如果可相等

        work(resCnt,deep+1,n);
        int tmpCnt = miniCnt[deep];
        for (int i=deep+1;i<n;++i)
            tmpCnt*=digitCnt[i];

        resCnt += tmpCnt;
    }else {

        int tmpCnt = miniCnt[deep];
        for (int i=deep+1;i<n;++i)
            tmpCnt*=digitCnt[i];

        resCnt += tmpCnt;
    }
}

int main() 
{
    freopen("input.txt","r",stdin);

    int LED[10][8]={
         0,1,1,1,0,1,1,1 //0
        ,0,0,0,1,0,0,1,0 //1
        ,0,1,0,1,1,1,0,1 //2
        ,0,1,0,1,1,0,1,1 //3
        ,0,0,1,1,1,0,1,0 //4
        ,0,1,1,0,1,0,1,1 //5
        ,0,1,1,0,1,1,1,1 //6
        ,0,1,0,1,0,0,1,0 //7
        ,0,1,1,1,1,1,1,1 //8
        ,0,1,1,1,1,0,1,1 //9
    };

    int T;
    cin>>T;

start:
    while (T--) {

        //init
        for (int i=0;i<12;++i) {
            for (int j=0;j<12;++j) {
                res[i][j] = 1;
            }
        }

        memset(digitCnt,0,sizeof(digitCnt));
        memset(miniCnt,0,sizeof(miniCnt));
        memset(equalCnt,0,sizeof(equalCnt));

        int K;
        cin>>K;
        int N;
        cin>>N;

        getchar();
        for (int i=0;i<K;++i) {

            while (1){
                char tmp;
                tmp = getchar();

                if(tmp == ' ')
                    continue;

                if(tmp=='\n')
                    break;

                for (int j=0;j<=9;++j) { //0-9个数字

                    if( 0 == LED[j][tmp-48] )
                        //与某个数字j不吻合
                        res[i][j] = 0; //此位不能为j
                }
            }
        }

        //输入完毕,得出res可以为的数字
        //判断N是几位数
        int highdigit = manyDigit(N);

        //前导0
        for (int i=0;i<K-highdigit;++i) {
            if( res[i][0] != 1 ) {
                //错误
                cout<<"0"<<endl;
                goto start;
            }
        }

        //N最高位,是否比之小的
        int tmpDigit = getDigit(N,highdigit);
        int tmpFlag = 0;
        for (int i=0;i<=tmpDigit;++i) {
            if( res[K-highdigit][i] == 1 ) {
                tmpFlag = 1;
                break;
            }
        }
        if (tmpFlag == 0) {
            //错误
            cout<<"0"<<endl;
            goto start;
        }

        for (int i=K-highdigit;i<K;++i) {

            for(int j=0;j<=9;++j) {
                if(res[i][j] == 1) {
                    digitCnt[i]++;
                    if( j<getDigit(N,K-i) )
                        miniCnt[i]++;

                    else if(j == getDigit(N,K-i))
                        equalCnt[i]++;
                }
            }
        }

        //计算个数
        int resCnt = 0;
        int deep = K-highdigit;
        work(resCnt,deep,K);

        cout<<resCnt<<endl;
        //system("pause");
    }//while(T--)

    return 0; 
}

暴力:

#include <iostream>
#include <vector>
using namespace std;

void getNum(vector<vector<int>> numList, int deep, int temp, vector<int> &totalNums);

int main(void)
{
    int deng[10][7] = { {1,1,1,0,1,1,1},//0
    {0,0,1,0,0,1,0},
    {1,0,1,1,1,0,1},
    {1,0,1,1,0,1,1},
    {0,1,1,1,0,1,0},
    {1,1,0,1,0,1,1},
    {1,1,0,1,1,1,1},
    {1,0,1,0,0,1,0},//7
    {1,1,1,1,1,1,1},
    {1,1,1,1,0,1,1}//9
    };

    int S_test; //测试点的个数
    int K_LED;    //K个LED数码管
    int compareNum; //给定每个测试点比较的数

    cin>>S_test;

    int *endAnswer = new int[S_test]; //输出结果

    for(int i=0;i<S_test;i++) //测试用例
    {
        cin>>K_LED>>compareNum; //K个LED数码管, 测试的数字
        cin.ignore(); //忽略上一行的换行符!!!

        vector<vector<int>>num_K_LED; //存储每个LED可能的数字

        for (int j=0;j<K_LED;j++) //多少LED数码管 就多少行
        {
            char eachLine[100]; //每行表示对应数码管已点亮的二极管的情况

            cin.getline(eachLine,100);//cin>>eachLine;      //每行

            int servenLight[7] = {0};   //单个LED的7个指示灯哪个亮
            int idx = 0; //数组下标
            for(int k=0;k<strlen(eachLine);k++) //每行转为数字
            {               
                if(eachLine[k]!=' ')
                {
                    servenLight[idx] = int(eachLine[k] - '0'); //取数字
                    idx++;
                    if(idx == 7)
                    {
                        break;
                    }
                }
            }

            vector<int > num_eachLED; //记录单个LED中servenLight[7]中亮的可能是哪些数字?
            for (int deng_i = 0; deng_i <10;deng_i ++) //循环0-9,符合的加入num_eachLED
            {
                bool rs = true;
                int idx = 0;

                while (servenLight[idx] !=0)  //所有亮的指示灯都在 这个数字中
                {
                    if(deng[deng_i][ servenLight[idx] -1] != 1)
                    {
                        rs = false;                     
                        break;
                    }
                    idx++;
                }
                if(rs)
                {
                    num_eachLED.push_back(deng_i);
                }                               
            }

            num_K_LED.push_back(num_eachLED);
        }


        vector<int> totalNums; //记录所有组合出来的数字
        int deep =0; 
        int temp =0;
        getNum(num_K_LED, deep, temp, totalNums);

        int count = 0;
        for (int totalNums_i = 0; totalNums_i < totalNums.size();totalNums_i++)
        {
            if(compareNum >= totalNums[totalNums_i])
            {
                count++;
            }
        }
        endAnswer[i] = count;
    }

    for(int i = 0; i<S_test; i++)
    {
        cout<<endAnswer[i]<<endl;
    }


    //system("pause");
    return 0;
}

void getNum(vector<vector<int>> numList, int deep, int temp, vector<int> &totalNums)
{
    if(deep < numList.size()-1)
    {
        for(int i=0; i < numList[deep].size(); i++)
        {
            int newInt = temp + numList[deep][i] * pow(10,numList.size()- deep -1);
            getNum(numList, deep+1, newInt,totalNums);
        }
    }
    else if(deep == numList.size()-1)
    {
        for(int i=0; i < numList[deep].size(); i++)
        {
            int newInt = temp + numList[deep][i] * pow(10,numList.size()- deep -1);
            totalNums.push_back(newInt);
        }
    }
}
【云栖快讯】阿里云栖开发者沙龙(Java技术专场)火热来袭!快来报名参与吧!  详情请点击

网友评论

this_is_bill
文章436篇 | 关注12
关注
为企业和开发者提供稳定、安全、智能的把网站域名或应用资源转换为计算机用于互连的数字 IP地址... 查看详情
是一款简单高效的电子邮件发送服务,它构建在可靠稳定的阿里云基础之上,帮助您快速、精准地实现事... 查看详情
结合大数据能力帮助电商企业快速搭建平台、应对业务高并发,剖析秒杀、视频直播等场景 查看详情
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效... 查看详情
双12

双12