2017级《程序设计基础(B)II》期末机考题解

本文介绍了一系列编程挑战,包括帮小I选择最满意宾馆的算法、操作小球位置的游戏实现、计算接近黄金分割数列的生成、特殊扑克牌游戏的最优解法、预测宝可梦大赛冠军属性的程序、变换全排列的最少步骤、以及规划Fish旅行路径的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

小 I 去天津玩啦,一路上,他跟他的同学发生了许多有趣的事。

到了晚上了,小 I 跟他的同学们要选一个宾馆住下了。但是形形色色的宾馆让小 I 不知所措。

对于一个宾馆来说,有许多特征,比如「价格」、「舒适度」。小I会对每个特征都有一个满意度。

小I会选择出满意度更高一些的宾馆。

其中,「价格」对于小 I 来说是最重要的,其次是「舒适度」。

如果有两个宾馆,如果对「价格」的满意度相同,那么根据「舒适度」进行选择;如果有多个宾馆条件相同,输出编号最小的宾馆。

小 I 现在处于水深火热之中,因为他们面对一堆宾馆不知所措,他想到了会编程的你,如果你不帮他选出来,他可能就会露宿街头了QAQ~

你能帮他按照他的意愿找到小I最满意的宾馆吗?

Input

多组输入,对于每组输入:

  • 给出 n (n <= 5000) 代表 n  个宾馆(编号从 1 - n),随后有 n 行数据。
  • 每行数据有两个整数,分别代表小I对「价格」、「舒适度」的满意程度,数值越大满意程度越高,满意度的范围从0 - 5000。
Output

输出按照描述的条件中小I最满意的宾馆编号,如果有多个宾馆条件相同,输出编号最小的宾馆。

Sample Input
4
0 1
1 0
1 1
1 0
Sample Output
3
结构体
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,i,j,a,b;
    int maxx,x,y;
    while(cin>>n)
    {
        x=-1,y=-1;
        for(i=0;i<n;i++)
        {
            cin>>a>>b;
            if(a>x||(a==x&&b>y))
            {
                maxx = i+1;
                x = a,y= b;
            }
        }
        cout<<maxx<<endl;
    }
    return 0;
}

B

给你n个小球,从左到右编号依次为1,2,3,4,5,6.........n排成一行。现在有以下2种操作:A x y表示把编号为x小球移动到编号为y的小球的左边(和y相邻)。Q x为询问编号为x的小球左边的球号,如果x左边没有小球的话输出"cyk666"。

Input

第一行输入一个T,表示有T组测试数据。(1<=T<=100)

随后每一组测试数据第一行是两个整数N,M,其中N表示球的个数(1 随后有M行询问,第一个字符是操作类型s。

当s为'A'时,输入x,y表示把编号为x小球移动到编号为y的小球的左边。

当s为'Q'时,输入x表示询问小球x左边的球号。保证(1<=x<=N,1<=y<=N)

Output

输出每次询问的球号,如果这样的小球不存在,输出"cyk666"(不包括引号)。

Sample Input
1
6 5
A 1 2
A 1 4
A 3 5
Q 5
Q 2
Sample Output
3
cyk666
Hint
Source

#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
struct node
{
    int data;
    node *last,*next;
}a[1000050];
int main()
{
    int t,n,i,j,m,x,y;
    char c;
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            a[i].next = &a[i+1];
            a[i].last = &a[i-1];
            a[i].data = i;
        }
        while(m--)
        {
            getchar();
            scanf("%c",&c);
            //cout<<c<<endl;
            if(c == 'A')
            {
                scanf("%d%d",&x,&y);
                a[x].next->last = a[x].last;
                a[x].last->next = a[x].next;
                a[x].last = a[y].last;
                a[y].last->next = &a[x];
                a[x].next = &a[y];
                a[y].last = &a[x];
            }
            if(c == 'Q')
            {
                scanf("%d",&x);
                if(a[x].last->data == 0)
                    printf("cyk666\n");
                else
                    printf("%d\n",a[x].last->data);
            }
        }
    }
    return 0;
}

C

    在古希腊时期,有一天毕达哥拉斯走在街上,在经过铁匠铺前他听到铁匠打铁的声音非常好听,于是驻足倾听。他发现铁匠打铁节奏很有规律,这个声音的比例被毕达哥拉斯用数学的方式表达出来。

    这个比例就叫做黄金分割比,它是指将整体一分为二,较大部分与整体部分的比值等于较小部分与较大部分的比值,其比值约为0.6180339887。这个比例被公认为是最能引起美感的比例,因此被称为黄金分割。 

    现在小玉有一个正整数数列,这个数列的前一项和后一项的比值十分趋近于黄金分割比,即(a[i])/(a[i+1])~ 0.6180339887,(i>=1),可是她只知道数列的第一项是5,现在她想通过已有条件推断出数列的任意项,请你帮助她编写一个程序计算。(请留意题目提示)

Input

多组输入

每次输入一个整数n(1<=n<=20)

Output

输出一个数,代表这个数列的第n项a[n]。

Sample Input
1
2
3
Sample Output
5
8
13
Hint

可以通过手动计算出数列的前几项发现某种规律,请不要直接在程序中利用首项乘以黄金分割比计算第n项。

此数列与斐波那契数列有关。斐波那契数列数列 :1 1 2 3 5 8 13 。。。


#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
int a[33];
int main()
{
    int n,i,j;
    a[0]=1;a[1]=2;a[2]=3;
    for(i=3;i<=25;i++)
    {
        a[i] = a[i-1]+a[i-2];
    }
    while(cin>>n)
    {
        cout<<a[n+2]<<endl;
    }
    return 0;
}

D

小 I 去天津玩啦,一路上,他跟他的同学发生了许多有趣的事。

]机智的小 I 和他的同学们决定玩一个游戏:

给你一副特殊的扑克牌,相同数字的扑克只有 3 种花色

出牌方式有且只有:

  1. 三张数字一样的牌带任意一张
  2. 单出任意一张

假如你现在有数字 1 - n 的共 3 * n 张的扑克牌(每个数字有 3 张花色),你需要计算出 最少几次可以出完这些牌。

请你编程帮助他计算出「最少需要多少次能出完这 3 * n张牌」。(请留意题目下方的提示)

Input

多组输入,每组输入只有一行,给出一个 n(1 <= n <= 100)。

Output

 

对于每组输入,输出一行,表示最少需要几次能出完牌。
 

Sample Input
1
3
Sample Output
3
3
Hint
  • 对于第一组样例:有 3 张 1。次数最少的出牌方法是:三次出牌,每一次出一张1。
  • 对于第二组样例:有 3 张 1 、3 张 2 、3 张 3。次数最少的出牌方法是:三张 1 带一张 3 、三张 2 带一张 3、 一张 3。
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
int a[33];
int main()
{
    int n,i,j;

    while(cin>>n)
    {
        i = n / 4;
        j = n % 4;
        if(j!=0)
            i++;
        cout<<3*i<<endl;
    }
    return 0;
}

E

去年冬天,皮卡丘认识了大家,因此皮卡丘决定给大家举办一场欢快的party。

这次party最大的活动就是宝可梦对战大赛,这次比赛是一场淘汰赛,由2^n位训练家进行n轮1v1的对战。每轮对战后,胜者晋级,败者淘汰,最终决出冠军。

训练家使用的宝可梦分为水、火、草三种属性,其中火属性宝可梦可以战胜草属性宝可梦,水属性宝可梦可以战胜火属性宝可梦,草属性宝可梦可以战胜水属性宝可梦,相同属性进行对战时则比拼宝可梦实力。

现在选手都已经领到了自己的编号,第一轮会由1号和2号进行对战,3号和4号进行对战……第二轮自然就是1号与2号之间的胜利者对战3号与4号之间的胜利者……

请你准确的预测一下本次宝可梦对战大赛的冠军会使用什么属性的宝可梦。

Input

第一行输入一个整数n(2<=n<=10),代表会进行n轮比赛。

第二行按编号顺序输入2^n个整数,整数范围为1、2、3,其中1代表训练家使用水属性宝可梦,2代表训练家使用火属性宝可梦,3代表训练家使用草属性宝可梦。

Output

输出一个整数,代表最终冠军使用的宝可梦的属性。

Sample Input
3
1 3 2 1 2 3 1 2
Sample Output
3

#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
int a[12][1050];
int ok(int x,int y)
{
    if(x==y)
        return x;
    if((x==1&&y==2)||(x==2&&y==1))
        return 1;
    if((x==2&&y==3)||(x==3&&y==2))
        return 2;
    else
        return 3;
}
int main()
{
    int n,i,j,top;
    cin>>n;
    for(i=1;i<=pow(2,n);i++)
    {
        scanf("%d",&a[1][i]);
    }
    for(i=1;i<=n;i++)
    {
        top=1;
        for(j=1;j<=pow(2,n-i+1);j+=2)
        {
            a[i+1][top++] = ok(a[i][j],a[i][j+1]);
        }
    }
    cout<<a[n+1][1]<<endl;
    return 0;
}
 

F

小鑫今天从玄黄那里拿到了一个长度为n的全排列,可是小鑫不喜欢这个全排列,于是小鑫想要把这个全排列变成他希望的样子。

但是全排列不是随便就能变换的,全排列每次变换只能交换相邻的两个数位。例如:123可以通过一步变换变成132,但是不能通过一步变换变成321。

现在你能帮助小鑫把他从玄黄那里拿到的全排列变成他希望的样子吗?小鑫想知道最少需要多少步变换才能将手里的全排列变成他希望的样子。

Input

第一行输入一个整数n(3<=n<=9),代表全排列的长度。

第二行输入一个长度为n的全排列,相邻两个数字之间用空格隔开,代表这是小鑫开始获得的全排列。

第三行输入一个长度为n的全排列,相邻两个数字之间用空格隔开,代表小鑫希望获得的全排列。

Output

输出一个整数,代表从第一个全排列变成第二个全排列最少需要进行的变换次数。

Sample Input
4
1 2 4 3
3 2 1 4
Sample Output
4
Hint

第一步,将1和2交换变为2 1 4 3

第二步,将4和3交换变为2 1 3 4

第三步,将1和3交换变为2 3 1 4 

第四步,将2和3交换变为3 2 1 4


#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a[12],b[12];
    int n,i,j;
    cin>>n;
    int ans = 0;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(j=1;j<=n;j++)
        cin>>b[j];
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(a[i]==b[j])
            {
                a[i] = j;
                break;
            }
        }
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n-i;j++)
        {
            if(a[j] > a[j+1])
            {
                int t =a[j];
                a[j] = a[j+1];
                a[j+1] = t;
                ans++;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

G

Fish 真的非常喜欢打游戏,最近又沉迷于塞尔达传说,现在 Fish 刚刚打通了雷咒盖侬解放了神兽瓦·纳波利斯,准备前往死亡火山去挑战火咒盖侬。

 

现在 Fish 刚刚回到了格鲁德小镇上,我们知道死亡火山在地图的右上角,但是格鲁德小镇在地图的左下角,之间有非常远的距离,地图上会有不少的驿站用来休息,但是 Fish 不想为了路过驿站而走远路,现在 Fish 想安排一个旅行的路线,使得经过的驿站尽可能的多,请你编写一个程序帮助他!

 

抽象一下题意,在一个二维坐标轴上,现在给出起点终点和 N 个点 Pi 的坐标,选择尽可能多的点组成一个序列,使得序列中点的 x 和 y 坐标都是递增的。

Input

多组输入(不超过10组)

 对于每组数据:

  • 第一行包括四个数 x1,y1,x2,y2,分别代表起点的横纵坐标,终点的横纵坐标(x1 < x2, y1 < y2)
  • 第二行输入一个整数 N,代表有 N 个点
  • 接下来 N 行,每行输入一个点的坐标 xi,yi 

 

0 <= N <= 1000

保证所有点的坐标大小在 32 位整数之内

Output

每组数据输出一行整数,为找出的最长序列长度(包含起点和终点)

Sample Input
1 1 9 9
5
0 8
3 2
3 3
4 3
7 1
Sample Output
4
Hint

第一组样例找出的最长序列只有 {(1, 1), (3, 2), (4, 3), (9, 9)} 长度为 4


#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
struct node
{
    int x,y;
}a[1000];
bool cmp(node a,node b)
{
    if(a.x!=b.x)
    {
        return a.y<b.y;
    }
    return a.x<b.x;
}
int dp[1000];
int main()
{
    int n,m,i,j,x,y,x1,x2,y1,y2,top;
    while(cin>>x1>>y1>>x2>>y2)
    {
        cin>>n;
        top=0;
        for(i=0;i<n;i++)
        {
            cin>>x>>y;
            if(x>x1&&y>y1&&x<x2&&y<y2)
            {
                a[top].x = x;
                a[top++].y = y;
            }
        }
        sort(a,a+top,cmp);
        memset(dp,0,sizeof(dp));
        int maxx = 1;
        for(i=0;i<top;i++)
        {
            maxx = 1;
            for(j=0;j<i;j++)
            {
                if(a[i].y>a[j].y&&a[i].x>a[j].x)
                {
                    maxx = max(dp[j]+1,maxx);
                }
            }
            dp[i] = maxx;
        }
        maxx = -1;
        for(i=0;i<top;i++)
        {
            maxx = max(maxx,dp[i]);
        }
        cout<<maxx+2<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值