zoukankan      html  css  js  c++  java
  • 2015年秋季大学先修课考试 解题报告

    A:电话费

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    每到月初,小明都会收到中国移动的扣费通知。小明很喜欢打电话,每个月的电话费都很多,所以他去办了优惠套餐。假设小明这个月打了n次电话,小明可以选择不交其中s次电话的话费。小明算术能力很差,请帮帮他算一下这个月最少要交多少话费。

    输入
    输入包含两行:第一行为这个月打的电话数n,可以免费的电话数s,其中0 < s,n < 100;第二行包含n个实数,为每次电话的话费。每行中的二个数据之间均已空格间隔。
    输出
    输出只有一行,为小明这个月最少要交的话费(保留1位小数)。
    样例输入
    7 3
    2.0 1.2 3.1 0.6 4.1 1.7 1.2
    样例输出
    4.7
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 101
    int n,s;
    double a[N];
    #include<algorithm>
    int main()
    {
        scanf("%d%d",&n,&s);
        for(int i=1;i<=n;++i)
        {
            scanf("%lf",&a[i]);
        }
        sort(a+1,a+n+1);
        double sum=0;
        for(int i=1;i<=n-s;++i)
        sum+=a[i];
        printf("%0.1f",sum);
        return 0;
    }
    View Code

    B:三个三位数的关系

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    将 1 到 9 这九个数字分成三个 3 位数,要求第一个 3 位数,正好是第二个 3 位数的一半,是第三个 3 位数的三分之一。问该如何分。

    输入
    没有输入。
    输出
    按第一个数从小到大输出满足条件的方案,每个方案占一行。方案中每个数之间用一个空格分开。
    样例输入
    没有输入。
    样例输出
    就不告诉大家答案了: )
    #include<iostream>
    using namespace std;
    #include<cstdio>
    bool judge(int a,int b,int c)
    {
        int flag[10]={0};
        if(a<100||b<100||c<100) return false;
        for(int i=1;i<=3;++i)
        {
            int k=a%10;
            flag[k]++;
            if(flag[k]>1)
            return false;
            a/=10;
        }
        for(int i=1;i<=3;++i)
        {
            int k=b%10;
            flag[k]++;
            if(flag[k]>1)
            return false;
            b/=10;
        }
        for(int i=1;i<=3;++i)
        {
            int k=c%10;
            flag[k]++;
            if(flag[k]>1)
            return false;
            c/=10;
        }
        return true;
    }
    int main()
    {
        int a;
        for(int i=300;i<=3000;++i)
        {
            if(i%6==0)
            {
                a=i/6;
                int b=2*a;
                int c=3*a;
                if(judge(a,b,c))
                {
                    printf("%d %d %d
    ",a,b,c);
                }
            }
        }
        return 0;
    }
    View Code

    C:找到第一个遗漏的实验

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    小王是北京大学医学部的学生。一天,教授让小王帮忙做一系列的医学实验,实验是从1开始标号的,按照自然数顺序,最大不超过100个。每个实验会得到一张实验结果的表格,表格标号就是实验标号。一个月后,小王做完了所有的实验,但是粗心的小王同学遗失了几张实验结果的表格。小王只能把遗失的实验结果重新做一遍,这时,小王想要知道按照从1开始的自然数顺序里,第一个需要补充做的实验是哪个。

    输入
    第一行为一个整数n,代表未遗失的所有实验结果表格的数量 
    第二行为n个整数,代表未遗失实验结果表格的标号
    输出
    输出为1行,输出按照自然数顺序,第一个需要重做的实验。
    样例输入
    5
    2 1 5 10 11
    样例输出
    3
    提示
    第二行输入类似 1 2 3 4 5这样从1开始的连续的自然数时,代表第6个实验是第一个需要重做的实验,所以应该输出6。
    #include<iostream>
    using namespace std;
    #include<cstdio>
    int n;
    bool flag[200]={0};
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            flag[x]=true;
        }
        for(int i=1;i<=2*n;++i)
        if(!flag[i])
        {
            printf("%d
    ",i);
            break;
        }
        return 0;
    }
    View Code

    D:流感传染

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    有一批易感人群住在网格状的宿舍区内,宿舍区为n*n的矩阵,每个格点为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人得了流感,以后每天,得流感的人会使其邻居传染上流感,(已经得病的不变),空房间不会传染。请输出第m天得流感的人数。

    输入
    第一行一个数字n,n不超过100,表示有n*n的宿舍房间。
    接下来的n行,每行n个字符,’.’表示第一天该房间住着健康的人,’#’表示该房间空着,’@’表示第一天该房间住着得流感的人。
    接下来的一行是一个整数m,m不超过100.
    输出
    输出第m天,得流感的人数
    样例输入
    5
    ....#
    .#.@.
    .#@..
    #....
    .....
    4
    样例输出
    16
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 150
    int jz[N][N];
    #include<cstring>
    int n,m;
    struct node{
        int x,y;
    };
    int xx[]={0,0,1,-1};
    int yy[]={1,-1,0,0};
    node dl[N*N],dlhb[N*N];
    int head=0,tail=0,head1=0,tail1=0;
    int sum=0;
    void input()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            char s[N];
            scanf("%s",s+1);
            for(int j=1;j<=n;++j)
            {
                if(s[j]=='.')
                jz[i][j]=1;
                if(s[j]=='@')
                {
                    jz[i][j]=0;
                    ++tail;
                    dl[tail].x=i;
                    dl[tail].y=j;
                    sum++;
                }
                if(s[j]=='#')
                {
                    jz[i][j]=1000000;
                }
            }
        }
        scanf("%d",&m);
    
    }
    void BFS()
    {
        int t=1;
        while(1)
        {
          if(t==m) break;
          while(head<tail)
          {
            ++head;
            int x1=dl[head].x,y1=dl[head].y;
            for(int i=0;i<4;++i)
            {
                int x2=x1+xx[i],y2=y1+yy[i];
                if(x2>=1&&x2<=n&&y2>=1&&y2<=n&&jz[x2][y2]==1)
                {
                    jz[x2][y2]=0;
                    sum++;
                    ++tail1;
                    dlhb[tail1].x=x2;
                    dlhb[tail1].y=y2;
                }
            }
             
           }
           t++;
           if(t==m) break;
           while(head1<tail1)
          {
            ++head1;
            int x1=dlhb[head1].x,y1=dlhb[head1].y;
            for(int i=0;i<4;++i)
            {
                int x2=x1+xx[i],y2=y1+yy[i];
                if(x2>=1&&x2<=n&&y2>=1&&y2<=n&&jz[x2][y2]==1)
                {
                    jz[x2][y2]=0;
                    sum++;
                    ++tail;
                    dl[tail].x=x2;
                    dl[tail].y=y2;
                }
            }
             
           }
           t++;
           if(t==m) break;
        }
        printf("%d",sum);
    }
    int main()
    {
        input();
        BFS();
        return 0;
    }
    View Code

    E:字符串最大跨距

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    有三个字符串S,S1,S2,其中,S长度不超过300,S1和S2的长度不超过10。想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并在S中互不交叉(即,S1的右边界点在S2的左边界点的左侧)。计算满足上述条件的最大跨距(即,最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。如果没有满足条件的S1,S2存在,则输出-1。 

    例如,S = "abcd123ab888efghij45ef67kl", S1="ab", S2="ef",其中,S1在S中出现了2次,S2也在S中出现了2次,最大跨距为:18。

    输入
    三个串:S1, S2, S3,其间以逗号间隔(注意,S1, S2, S3中均不含逗号和空格);
    输出
    S1和S2在S最大跨距;若在S中没有满足条件的S1和S2,则输出-1。
    样例输入
    abcd123ab888efghij45ef67kl,ab,ef
    样例输出
    18
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 1001
    char ss[N+N];
    char s[N+10],s1[N/2],s2[N/2];
    #include<cstring>
    int lens,len1=0,len2=0,lenss;
    void input()
    {
        scanf("%s",ss+1);
        lenss=strlen(ss+1);
        int i;
        for(i=1;i<lenss&&ss[i]!=',';++i)
        s[i]=ss[i];
        lens=i;
        for(i=i+1;ss[i]!=',';++i)
        {
            s1[++len1]=ss[i];
        }
        for(i=i+1;ss[i]!='';++i)
        s2[++len2]=ss[i];
    }
    bool judge_1(int l,int r)
    {
        for(int i=1;l<=r&&i<=len1;++l,++i)
        if(s1[i]!=s[l]) return false;
        return true;
    }
    bool judge_2(int l,int r)
    {
        for(int i=1;l<=r&&i<=len2;++l,++i)
        if(s2[i]!=s[l]) return false;
        return true;
    }
    void chuli()
    {
        int ans[2]={0};
        for(int i=1;i<=lens-len1+1;++i)
        {
            if(judge_1(i,i+len1-1))
            {
                ans[0]=i+len1-1;
                break;
            }
        }
        for(int i=lens-len2+1;i>=1;--i)
        {
            if(judge_2(i,i+len2-1))
            {
                ans[1]=i;
                break;
            }
        }
        if(ans[0]==0||ans[1]==0||ans[0]>ans[1])
        printf("-1");
        else printf("%d",ans[1]-ans[0]-1);
    }
    int main()
    {
        input();
        chuli();
        return 0;
    }
    View Code

    F:最大零矩阵

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    有一个二位数组 m(< 100)行, n(< 100) 列,其元素为不大于100的非负整数。现要找元素值均为0的最大子二维数组,其中行相邻,列也相邻,行数与列数之积最大(即,所含0元素最多),输出该最大积。例如: 

    2  5  0  0  8  11  15 
    3  0  0  0  0  12  16 
    7  0  0  0  0  13  17 
    8  0  0  7  1  14  18 
    4  0  0  0  0  0   0 
    6  0  0  0  0  0   0 

    这是6行,7列构成的二维数组,其中:由第4~5行(最后2行),第1~6列(最后6列)构成的子数组最大,共有12个0元素,因此,应该输出 12。其它情况下的子数组都不多于12个0元素,例如,第1~5行与第1~2列构成子数组为第二大数组,含有10个0元素。 

    输入
    第一行,m 和 n 的值,以空格间隔,m 和 n 均为 不大于 100 的正整数 
    之后,共 m 行,每行共 n 个元素,其间用空格间格。
    输出
    输出,最大零元素子二维数组所含的 0 元素个数,如果没有0元素,则输出0。
    样例输入
    6 7
    2  5  0  0  8  11  15
    3  0  0  0  0  12  16
    7  0  0  0  0  13  17
    8  0  0  7  1  14  18
    4  0  0  0  0  0   0
    6  0  0  0  0  0   0
    样例输出
    12
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 150
    int f[N][N];
    int h[N],l[N],r[N];
    #include<cstring>
    int n,m;
    int ans=-1;
    bool flag=false;
    void input()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;++i)
          for(int j=1;j<=n;++j)
          {
              scanf("%d",&f[i][j]);
              if(f[i][j]==0)
              flag=true;
          }
    }
    void chuli()
    {
        memset(h,0,sizeof(h));
        for(int i=1;i<=m;++i)
        {
            int l1,l2;
            for(int j=1;j<=n;++j)
            if(f[i][j]==0)
            h[j]++;
            else h[j]=0;
            for(int j=2;j<=n;++j)
            {
                if(f[i][j]!=0) continue;
                l1=j;
                while(l1>1&&h[l1]>=h[j])
                l1--;
                l[j]=j-l1-1;
            }
            for(int j=n-1;j>=1;--j)
            {
                if(f[i][j]!=0) continue;
                l2=j;
                while(l2<n&&h[l2]>=h[j])
                l2++;
                r[j]=l2-j-1;
            }
            for(int j=1;j<=n;++j)
              ans=max(ans,h[j]*(l[j]+r[j]+1));
        }
        
    }
    int main()
    {
        input();
        if(!flag)
        {
            cout<<0<<endl;
        }
        else 
        {
            chuli();
            printf("%d",ans);
        }
        return 0;
    }
    View Code

    G:实数加法

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    求2个实数相加的和。

    输入输出中出现的实数都有如下的形式: P1P2...Pi.Q1Q2...Qj。对于整数部分,P1P2...Pi是一个非负整数;对于小数部分,至少有一位且最后一位Qj不等于0。

    输入
    2行,分别是两个加数。每个加数不超过100个字符。
    输出
    一行输出是相应的和。数据保证一定是一个小数部分不为0的实数。
    样例输入
    0.111111111111111111111111111111
    0.111111111111111111111111111111
    样例输出
    0.222222222222222222222222222222
    代码:
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<cstring>
    #define N 150000
    int lenint1[N],lenf1[N],lenint2[N],lenf2[N];
    int intans[N],lenint,floatans[N],lenfloat;
    int lenia,lenfa,lenib,lenfb;
    char ss[N];
    void input()
    {
        scanf("%s",ss+1);
        int lens=strlen(ss+1);
        int i;
        for(i=1;ss[i]!='.';++i);/*输入的时候,把小数位与整数位分别储存,进行计算*/
        lenia=0;
        for(int j=i-1;j>=1;--j)
        lenint1[++lenia]=ss[j]-'0';/*小数与整数都要倒序储存*/
        lenfa=0;
        for(int j=lens;j>=i+1;--j)
        lenf1[++lenfa]=ss[j]-'0';
        memset(ss,0,sizeof(ss));
        scanf("%s",ss+1);
        lens=strlen(ss+1);
        for(i=1;ss[i]!='.';++i);
        lenib=0;
        for(int j=i-1;j>=1;--j)
        lenint2[++lenib]=ss[j]-'0';
        lenfb=0;
        for(int j=lens;j>=i+1;--j)
        lenf2[++lenfb]=ss[j]-'0';
        if(lenfb<lenfa)/*特别注意这个地方:小数的加法不能直接像整数一样加,因为整数是低位对齐加,而小数必须是高位对齐加*/
        {
            int k=lenfa-lenfb;/*这就是对齐的过程,在位数少后面补上0*/
            for(int i=lenfb;i>=1;--i)
            lenf2[i+k]=lenf2[i];
            for(int i=1;i<=k;++i)
            lenf2[i]=0;
            lenfb=lenfa;
        }
        else     if(lenfa<lenfb)
        {
            int k=lenfb-lenfa;
            for(int i=lenfa;i>=1;--i)
            lenf1[i+k]=lenf1[i];
            for(int i=1;i<=k;++i)
            lenf1[i]=0;
            lenfa=lenfb;
        }
    }
    void add_1()
    {
        lenint=1;
        while(lenint<=lenia||lenint<=lenib)
        {/*注意这个地方必须是+=才可以,保存之前的进位*/
            intans[lenint]+=lenint1[lenint]+lenint2[lenint];
            intans[lenint+1]+=intans[lenint]/10;
            intans[lenint]%=10;
            lenint++;
        }
        if(intans[lenint]==0) 
        lenint--;
    }
    void add_2()
    {
        lenfloat=1;
        while(lenfloat<=lenfa||lenfloat<=lenfb)
        {
            floatans[lenfloat]+=lenf1[lenfloat]+lenf2[lenfloat];
            floatans[lenfloat+1]+=floatans[lenfloat]/10;
            floatans[lenfloat]%=10;
            lenfloat++;
        }
        if(floatans[lenfloat]==0) 
        lenfloat--;
    }
    void out()
    {
        if(lenfloat>max(lenfa,lenfb))/*注意二:判断小数是否向整数位进位,也就是总位数加长了*/
        {
            int k=floatans[lenfloat];
            lenfloat--;
            int m=1;
            intans[m]+=k;
            while(intans[m]>=10)
            {
                intans[m+1]++;
                intans[m]%=10;
                m++;
            }
            if(intans[lenint+1]!=0) lenint++;/*处理进位的过程*/
        for(int i=lenint;i>=1;--i)
        printf("%d",intans[i]);
        printf(".");
        int l=1;
        while(floatans[l]==0) l++;/*关键:删除小数位后面多余的0*/
        for(int j=lenfloat;j>=l;--j)
        printf("%d",floatans[j]);
        }
        else {
        for(int i=lenint;i>=1;--i)
        printf("%d",intans[i]);
        printf(".");
        int l=1;
        while(floatans[l]==0) l++;
        for(int j=lenfloat;j>=l;--j)
        printf("%d",floatans[j]);
        }
        return;
    }
    int main()
    {
        input();
        add_1();
        add_2();
        out();
        return 0;
    }
    View Code

    H:幼儿园分糖果

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述

    新年将至,幼儿园的老师们为小朋友们准备了各种各样的糖果。不同的小朋友所喜欢的糖果可能是不同的,为了让更多的小朋友得到他/她喜爱的糖果,幼儿园的老师们对小朋友们的“糖果偏好”(即哪位小朋友喜欢哪几种糖果)进行了统计。 
       
        现已知老师们共准备了F种糖果,准备为幼儿园里的N位小朋友分配糖果。同上所述,我们假设: 
    (1)每位小朋友只会接受自己喜欢的糖果,不接受自己不喜欢的糖果; 
    (2)每种糖果只能分给某一位小朋友(即:一旦某种糖果分给某位小朋友,则其他小朋友就不能再被分配到该种糖果); 
    (3)我们不保证所有小朋友都能获得糖果; 
    (4)每个小朋友喜欢哪种糖果将在输入数据中给出。 

        请你构造一个程序,帮助老师们分配糖果,以使得在上述条件下,老师们能够将现有糖果分配给最多的小朋友。请输出可分到糖果的小朋友的最多的人数。

    输入
    第1行为两个整数:N 和 F,以空格隔开。其中,N(1≤ N ≤ 20)表示小朋友的总人数;F(1 ≤ F ≤ 20)表示糖果的总种数(糖果种类分别用整数1,2,3,...,F进行编号)。 

    接下来有N行,每行包含多个以空格隔开的整数;其中,第一个整数m,表示某位小朋友所喜爱的糖果的种数,其后的m个整数,表示该小朋友所喜爱的糖果种类的编号序列。 
    例如:若某行的输入为“3 1 2 3”,则表示该位小朋友共喜欢3种类型的糖果,其糖果类型编号分别为“1”“2”“3”。
    输出
    仅一行,即在上述输入条件下,能分到糖果的小朋友的人数的最大值。
    样例输入
    4 3
    2 1 2
    2 2 3
    2 1 3
    2 1 3
    样例输出
    3
    代码:
    /*部分数据不过,需要用二分图匹配*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define N 21
    #include<algorithm>
    struct Child{
        int sum[N];
        bool operator <(const Child &p)
        const{return sum[0]<p.sum[0];}
    }child[N];
    bool cab[N]={0};
    int n,f;
    void input()
    {
        scanf("%d%d",&n,&f);
        for(int i=1;i<=n;++i)
        {
            int m;
            scanf("%d",&m);
            for(int j=1;j<=m;++j)
            {
                scanf("%d",&child[i].sum[j]);
            }
            child[i].sum[0]=m;
         } 
    }
    int sum=0;
    void chuli()
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=child[i].sum[0];++j)
            {
                if(!cab[child[i].sum[j]])
                {
                    cab[child[i].sum[j]]=true;
                    sum++;
                    break;
                }
            }
        }
    }
    int main()
    {
        input();
        sort(child+1,child+n+1);
        chuli();
        printf("%d
    ",sum);
        return 0;
    }
    View Code

    I:还是采药问题

    总时间限制: 
    1000ms
     
    内存限制: 
    65536kB
    描述
    辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 如果你是辰辰,你能完成这个任务吗? 
    输入
    输入第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
    输出
    输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
    样例输入
    70 3
    71 100
    69 1
    1 2
    
    样例输出
    3
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #define T 1201
    int f[T];
    int tim[T],val[T],t,m;
    void input()
    {
        scanf("%d%d",&t,&m);
        for(int i=1;i<=m;++i)
        scanf("%d%d",&tim[i],&val[i]);
    }
    void DP()
    {
        for(int i=1;i<=m;++i)
          for(int j=t;j>=tim[i];--j)
          f[j]=max(f[j],f[j-tim[i]]+val[i]);
        cout<<f[t]<<endl;
        return ;
    }
    int main()
    {
        input();
        DP();
        return 0;
    }
    View Code
     
     
  • 相关阅读:
    Spring整合MyBatis(一)MyBatis独立使用
    Spring AOP源码分析(三)创建AOP代理
    Spring AOP源码分析(二)动态A0P自定义标签
    Spring AOP源码分析(一)使用示例
    JDK(十)JDK1.7&1.8源码对比分析【集合】ConcurrentHashMap
    JDK(九)JDK1.7源码分析【集合】HashMap的死循环
    JDK(八)JDK1.7&1.8源码对比分析【集合】HashMap
    MySQL(五)SELECT语句执行顺序
    版本控制器:SVN
    springmvc
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5389643.html
Copyright © 2011-2022 走看看