2014年春季大学先修课考试 解题报告

A:吃糖果

总时间限制: 
1000ms
内存限制: 
65536kB
描述
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案。例如:如果N=1,则名名第1天就吃掉它,共有1种方案;如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案;如果N=4,则名名可以第1天吃1块,剩3块,也可以第1天吃2块,剩2块,共有3+2=5种方案。现在给定N,请你写程序求出名名吃巧克力的方案数目。
输入
输入只有1行,即整数N。
输出
输出只有1行,即名名吃巧克力的方案数。
样例输入
4
样例输出 5
/*一个裸裸的斐波那契数列*/
#include<cstdio>
#include<iostream>
using namespace std;
int n;
long long int f[30];
int main()
{
    scanf("%d",&n);
    f[1]=1;
    f[2]=2;
    for(int i=3;i<=n;++i)
    f[i]=f[i-1]+f[i-2];
    printf("%d\n",f[n]);
    return 0;
}
View Code

B:话题焦点人物

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

微博提供了一种便捷的交流平台。一条微博中,可以提及其它用户。例如Lee发出一条微博为:“期末考试顺利 @Kim @Neo”,则Lee提及了Kim和Neo两位用户。

我们收集了N(1 < N < 10000)条微博,并已将其中的用户名提取出来,用小于100的正整数表示。

通过分析这些数据,我们希望发现大家的话题焦点人物,即被提及最多的人(题目保证这样的人有且只有一个),并找出那些提及它的人。

输入
输入共两部分:
第一部分是微博数量N,1 < N < 10000。
第二部分是N条微博,每条微博占一行,表示为:
发送者序号a,提及人数k(0 < = k < = 20),然后是k个被提及者序号b1,b2...bk;
其中a和b1,b2...bk均为大于0小于100的整数。相邻两个整数之间用单个空格分隔。
输出
输出分两行:
第一行是被提及最多的人的序号;
第二行是提及它的人的序号,从小到大输出,相邻两个数之间用单个空格分隔。同一个序号只输出一次。
样例输入
5
1 2 3 4
1 0
90 3 1 2 4
4 2 3 2
2 1 3
样例输出 3 1 2 4
/*直接模拟:*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<algorithm>
#define N 10001/*这里为什么要把N开到10000这么大呢?考虑题目中的特殊数据,一开始我开到200,就过了8个点。
特殊数据:一万个微博 都提及了一个人,那么这个人的pre数据就要储存一万个人的信息,虽然最后还会去重,但是这时候确实很有可鞥越界 
*/
int pre[201][N],ans[2],sum[201];
int n,a,k,b;
void input()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&a,&k);
        for(int i=1;i<=k;++i)
        {
            scanf("%d",&b);
            sum[b]++;/*统计每个人被提及的次数*/
            if(sum[b]>ans[1])/*随时计入最大值*/
            {
                ans[1]=sum[b];
                ans[0]=b;
            }
            pre[b][0]++;/*记录提及b的人数和人的编号*/
            pre[b][pre[b][0]]=a;
        }
    }
}
void chuli()
{
    int an=ans[0];
    printf("%d\n",ans[0]);
    sort(pre[an]+1,pre[an]+pre[an][0]+1);/*这是题目中说的按照序号由小到大输出*/
    int p=0;
    for(int i=1;i<=pre[an][0];++i)
    {
        if(pre[an][i]!=p)/*输出时去重,相同的不输出,不同与p的输出,并且更新p,因为序列是升序的,所以这个方法可行*/
        {
            printf("%d ",pre[an][i]);
            p=pre[an][i];
        }
        else continue;
    }
}
int main()
{
    input();
    chuli();
    return 0;
}
View Code

C:完美立方

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

形如a3= b3 + c3 + d3的等式被称为完美立方等式。例如123= 63 + 83 + 103 。编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a3 = b3 + c3 + d3,其中a,b,c,d 大于 1, 小于等于N,且b<=c<=d。

输入
一个正整数N (N≤100)。
输出
每行输出一个完美立方。输出格式为:
Cube = a, Triple = (b,c,d)
其中a,b,c,d所在位置分别用实际求出四元组值代入。

请按照a的值,从小到大依次输出。当两个完美立方等式中a的值相同,则b值小的优先输出、仍相同则c值小的优先输出、再相同则d值小的先输出。
样例输入
24
样例输出
Cube = 6, Triple = (3,4,5)
Cube = 12, Triple = (6,8,10)
Cube = 18, Triple = (2,12,16)
Cube = 18, Triple = (9,12,15)
Cube = 19, Triple = (3,10,18)
Cube = 20, Triple = (7,14,17)
Cube = 24, Triple = (12,16,20)
",
#include<iostream>
using namespace std;
#include<cstdio>
int n;
int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;++i)
      for(int j=2;j<=n;++j)
        for(int k=2;k<=n;++k)
          for(int l=2;l<=n;++l)
         {
          if(j<=k&&k<=l&&i*i*i==j*j*j+k*k*k+l*l*l)            
           printf("Cube = %d, Triple = (%d,%d,%d)\n",i,j,k,l);
    
          }
    return 0;
 } 
View Code

D:478-3279

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

在美国,商家都喜欢用好记的电话号码。人们常用的方法就是把电话号码拼成一个便于记忆的词汇或者短语,比如你可以通过Gino比萨店的电话号码301- GINO来定比萨。另一个方法就是把电话号码分为成组的数字,比如你可以通过必胜客的电话“三个十”:3-10-10-10来定比萨。 
一个七位电话号码的标准形式是xxx-xxxx,如 123-4567。 
通常,电话上的数字与字母的映射关系如下 
A, B, C 映射到 2 
D, E, F 映射到 3 
G, H, I 映射到 4 
J, K, L映射到5 
M, N, O映射到6 
P, R, S映射到7 
T, U, V映射到8 
W, X, Y映射到9 
Q和Z并没有相关的映射。 
你的任务就是把一个七位电话号码转为标准的xxx-xxxx格式,其中x表示数字

输入
第一行为输入的电话号码个数n(n < 100), 下面n行每行表示一个七位号码,这些号数为了便于记忆可能不是标准格式,但一定是合法的。
输出
对于行输入,输出一个标准格式的电话号码
样例输入
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
样例输出
487-3279
487-3279
888-4567
310-1010
888-4567
888-4567
967-1111
310-4466
310-1010
888-1200
487-3279
487-3279
/*A, B, C 映射到 2 
D, E, F 映射到 3 
G, H, I 映射到 4 
J, K, L映射到5 
M, N, O映射到6 
P,q R, S映射到7 
T, U, V映射到8 
W, X, Yz映射到9 
Q和Z并没有相关的映射。 */
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
int n;
int s[100];
int iv[30]={0,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};
char pp[50];
int ans[50];
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d",&n);
    int i,j;
    for(i=1;i<=n;++i)
    {
        memset(ans,0,sizeof(ans));
        memset(pp,0,sizeof(pp));
        scanf("%s",pp+1);
        int t=0;
        int lenp=strlen(pp+1);
        for(j=1;j<=lenp;++j)
        {
            if(pp[j]>='A'&&pp[j]<='Z')
            {
                ++t;
                ans[t]=iv[pp[j]-'A'+1];
            }
            if(pp[j]>='0'&&pp[j]<='9')
            {
                ++t;
                ans[t]=pp[j]-'0';
            }

        }
        for(j=1;j<=t;++j)
        {
            printf("%d",ans[j]);
            if(j==3)
            {
                printf("-");
            }
        }
        printf("\n");
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
View Code

 

E:一类括号匹配问题

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

在程序设计中,常常使用小括号强调表达式的运算顺序,但是,左右小括号必须匹配。现给定一个不多于500个符号的表达式(串),其中可能存在多个小括号,想检查小括号的匹配问题。如果存在小括号不匹配,则输出 mismatch;如果所有小括号匹配,则按左右括号的匹配距离由小到大输出左、右括号的位置;若多个匹配的距离相等,则左括号先出现的匹配先输出;如果整个串中没有小括号,则左右位置均输出0,即 0,0; ,规定,串中第一个符号的位置为1。 
匹配距离=右括号位置 - 左括号位置。

例如: 
输入为:    (x+y*(z-5)*(x+y))*(x+98) 
输出为: 
6,10 
12,16 
19,24 
1,17 
如果输入为  (x+y*(z-5))*x+y) 
则不匹配,因为在最后的反括号没有相匹配的正括号。因此,输出: 
mismatch

输入
一串符号
输出
按匹配距离的增序输出匹配对的左右位置,逗号间隔;如果距离相同,则按左括号出现的先后顺序输出;如果整个序列中出现不匹配现象,则输出 mismatch;
样例输入
(x+y*(z-5)*(x+y))*(x+98)
样例输出 6,10 12,16 19,24 1,17 代码及其分析:
/*这是一个对于数据结构--栈的考察,遇到的第一个右括号,他的左面离他最近的那个(一定和他匹配,这就是栈的思路了,对于(先都压栈,如果遇到),就把栈顶的(弹出,和他匹配,把坐标记录下就可以了*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
struct Node{

    int l,r,len;
    bool operator<(const Node &p)
        const{
        if(len!=p.len)
        return len<p.len;
        else return l<p.l;
    }
};
int t=0;
#define N 1001
Node node[N];
char s[N];
int list[N],top=0;
int main()
{
    scanf("%s",s+1);
    int lens=strlen(s+1);
    int i,j,k,l;
    bool flag=true;
    for(i=1;i<=lens;++i)
    {
        if(s[i]=='(')
        {
            top++;/*压栈*/
            list[top]=i;
        }
        if(s[i]==')')
        {
            if(top>0)/*栈没空*/
            {
                ++t;
                node[t].l=list[top];/*储存坐标*/
                node[t].r=i;
                node[t].len=i-list[top];
                top--;
            }
            else {
                flag=false;/*这个)没有与之匹配的*/
                break;

            }
        }
    }
    if(!flag||top!=0)
    printf("mismatch\n");
    else if(t==0)/*没有括号*/
        printf("0,0\n");
    else{
        sort(node+1,node+t+1);
        for(i=1;i<=t;++i)
            printf("%d,%d\n",node[i].l,node[i].r);

    }
    system("pause");
    return 0;
}
View Code

 

F:棋盘问题

总时间限制: 
1000ms
内存限制: 
65536kB
描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
样例输入
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
样例输出 2 1 代码及其分析:
/*这个问题就是八皇后问题,不同的地方就是没有皇后的斜行攻击,但是棋盘不是均匀的,另外就是k!=n的问题,这个用循环试试每一行就行了*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#define N 10
char p[N][N];
bool flag[N];
int  jz[N][N];
int n,k;
int sum=0;
void dfs(int g,int i)
{
    if(g>k)return ;
    if(g<k&&i==n) return ;
    int j,l;
    for(j=1;j<=n;++j)
    {
        if(jz[i][j]&&!flag[j])
        flag[j]=true;
        else continue;
        if(g==k)
        {
            flag[j]=false;
            sum++;
        //    return;/*这里的return必须去掉,因为这一行可能放多种情况,不能知道一个就返回*/
        }
        for(l=i+1;l<=n;++l)
            dfs(g+1,l);
        flag[j]=false;
    }
}
void input()
{
    sum=0;
    memset(flag,0,sizeof(flag));
    memset(jz,0,sizeof(jz));
    memset(p,0,sizeof(p));
    int i,j,l;
    for(i=1;i<=n;++i)
    {
        char pp[N];
        scanf("%s",pp+1);
        for(j=1;j<=n;++j)
        {
            if(pp[j]=='#')
            {
                jz[i][j]=1;
            }
            else jz[i][j]=0;
        }

     }
}
int main()
{
    while(scanf("%d%d",&n,&k)==2&&n!=-1&&k!=-1)
    {
        input();
        for(int i=1;i<=n;++i)
            dfs(1,i);
        printf("%d\n",sum);
    }
    return 0;
}
View Code

 

G:多边形游戏

总时间限制: 
1000ms
内存限制: 
65536kB
描述
  一个多边形,开始有n个顶点。每个顶点被赋予一个正整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。 
    现在来玩一个游戏,该游戏共有n步: 
    第1步,选择一条边,将其删除 
    随后n-1步,每一步都按以下方式操作:(1)选择一条边E以及由E连接着的2个顶点v1和v2; (2)用一个新的顶点取代边E以及由E连接着的2个顶点v1和v2,将顶点v1和v2的整数值通过边E上的运算得到的结果值赋给新顶点。 

    最后,所有边都被删除,只剩一个顶点,游戏结束。游戏得分就是所剩顶点上的整数值。那么这个整数值最大为多少?
输入
第一行为多边形的顶点数n(n ≤ 20),其后有n行,每行为一个整数和一个字符,整数为顶点上的正整数值,字符为该顶点到下一个顶点间连边上的运算符“+”或“*”(最后一个字符为最后一个顶点到第一个顶点间连边上的运算符)。
输出
输出仅一个整数,即游戏所计算出的最大值。
样例输入
4
4 *
5 +
5 +
3 +
样例输出
70
提示 小规模问题可不必用动态规划方法编程求解,仅用递归就可以求解。计算中不必考虑计算结果超出整数表达范围的问题,给出的数据能保证计算结果的有效性。 在给的例子中,计算过程为(3+4)*(5+5)=70。 代码:虽然题目中说了可以不用动态规划做,但是毕竟环形DP也是一个难点,所以我就用了环形DP做了
/*f[i][j],表示从i这个顶点,延伸k个顶点(包括它自身),所能达到的最大值,
状态的转移:通过枚举中间的断点来实现*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#define N 45
int a[N],cha[N];
int f[N][N];
int n;
void input()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);/*因为是环形DP,所以预处理把它延伸成为两倍的链条*/
        a[n+i]=a[i];
        char s[5];
        scanf("%s",s+1);
        if(s[1]=='+')
        cha[n+i]=cha[i]=1;//1 表示+ 
        else cha[n+i]=cha[i]=2;// 2表示*
    }
}
void pre_chuli()
{
    memset(f,0,sizeof(f));
    for(int i=1;i<=2*n;++i)
    {
        f[i][1]=a[i];/*预处理延长1,2的情况*/
        if(cha[i]==1)
        f[i][2]=a[i]+a[i+1];
        else f[i][2]=a[i]*a[i+1];
    }
}
void DP()
{
    for(int j=3;j<=n;++j)
      for(int i=1;i+j-1<=2*n;++i)/*注意是循环到2*才可以*/
        for(int k=1;k<=j-1;++k)
        {
            if(cha[i+k-1]==2)
            f[i][j]=max(f[i][j],f[i][k]*(f[i+k][j-k]));
            else f[i][j]=max(f[i][j],f[i][k]+(f[i+k][j-k]));
        }
}
int main()
{
    input();
    pre_chuli();
    DP();
    int ans=-11;
    for(int i=1;i<=n;++i)
    ans=max(ans,f[i][n]);
    printf("%d\n",ans);
    return 0;
}
View Code

 





 

转载于:https://www.cnblogs.com/c1299401227/p/5374620.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值