2019北大計算機學科夏令營機試題目


2019北大計算機學科夏令營機試題目#

題目鏈接
密碼依然是fighting!

百練上北大夏令營的機試題目,但是很多都找不到可以提交網站的地方,只看了幾個能再Virtual Judge上的題目。感受就是題目很長,代碼量也不少,題目也有一定難度,時間也很短。總之就是“南”,這些人太厲害了吧!
大概有三個較為簡單的小模擬的題目。也沒有找到可以提交的OJ。

1.Hopscotch##

題目大意:跳房子的游戲,求一個數字變到另外一個數字最少操作步數。操作H和操作O分別定義如下:

  1. if the stone falls into a house (marked as H), we can jump from the current house i to the house 3*i;

  2. if the stone falls outside the house (marked as O), we can jump from the current house i to house i/2.(round down).
    題目保證操作步數再25步之內。
    題解:上面的條件很重要,使得這個題不考慮貪心和DP,而是BFS最短路的問題,因為深度最多25步,而且這個題需要保存路徑,輸出字典序最小的操作方案。
    代碼是別人寫的,找不到提交的地方。

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <queue>
using namespace std;
int n, m;
struct node
{
    int index;
    int step;
    vector<char> s; //記錄路徑
};
void BFS()
{
    map<int, bool> mp;
    queue<node> q;
    node temp;
    temp.index = n;
    temp.step = 0;
    q.push(temp);
    while (!q.empty())
    {
        node top = q.front();
        q.pop();
        for (int i = 0; i < 2; i++)
        {
            node temp = top;
            if (i == 0)
            {
                temp.index = top.index * 3;
                temp.step = top.step + 1;
                if (!mp[temp.index])
                {
                    temp.s.push_back('H');
                    q.push(temp);
                    mp[temp.index] = true;
                }
            }
            else
            {
                temp.index = top.index / 2;
                temp.step = top.step + 1;
                if (!mp[temp.index])
                {
                    temp.s.push_back('O');
                    q.push(temp);
                    mp[temp.index] = true;
                }
            }
            if (temp.index == m)
            {
                int len = temp.s.size();
                cout << len << endl;
                for (int i = 0; i < len; i++)
                {
                    cout << temp.s[i];
                }
                cout << endl;
                return;
            }
        }
    }
}

int main()
{
    while (cin >> n >> m)
    {
        if (n == 0 && m == 0)
        {
            break;
        }
        BFS();
    }
    return 0;
}

2. Falling Leaves##

題目大意:
一個二叉搜索樹,不斷刪除樹的葉子,給出葉子信息,求這個二叉搜索樹的先序遍歷。
題解:
逆向讀取輸入信息,也就是從頂向下構建這個二叉搜索樹,建樹之后先序遍歷即可。建樹操作還可以更加熟練一下。

#include <iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
const int N=30;
struct node{
    char c;
    node *l,*r;
    node(char c='a',node *l=NULL,node *r=NULL):c(c),l(l),r(r){}
};
node tree[30];
int id;
node *insertTree(node *rt,char val){
    if(rt==NULL){
        tree[id].c=val;
        tree[id].l=NULL;
        tree[id].r=NULL;
        return &tree[id++];//這里的下標不重要,只需要保存全部結點
    }
    if(val<rt->c)rt->l=insertTree(rt->l,val);
    else rt->r=insertTree(rt->r,val);
    return rt;
}
void preOrder(node *rt){
    if(rt){
        putchar(rt->c);
        preOrder(rt->l);
        preOrder(rt->r);
    }
}
int main()
{
    vector<char>ve;
    char ch;
    while(cin>>ch&&ch!='$'){
        ve.clear();
        ve.push_back(ch);
        while(cin>>ch){
            if(ch=='*'||ch=='$')break;
            ve.push_back(ch);
        }
        node *root=NULL;
        id=0;
        for(int i=ve.size()-1;i>=0;i--){
            root=insertTree(root,ve[i]);
        }
        preOrder(root);
        puts("");
    }
    return 0;
}

3.昂貴的聘禮##

題目大意:
交換物品,不同等級的人有不同的物品交換,交換中需要支付一定的錢。eg:物品A+100=物品B。
限制條件是,在全部交換過程中,最高等級的人和最低等級的人等級差不能超過M。
題解:
原本還以為是DP,結果是我傻了。最短路問題,加上枚舉最低等級為minLevel的交換者,那么合法的交換者就是等級為minLevel到minLevel+M之間的人。交換建圖,額外付出的錢為路徑cost,注意方向性。時空復雜度可過,使用Dijkstra的朴素寫法即可。

#include <iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int m,n;
const int N=105;
const int INF=0x3f3f3f3f;
int price[N],level[N];
int edge[N][N];
int vis[N];
int d[N];
void init(){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            edge[i][j]=INF;
        }
    }
    for(int i=0;i<n;i++){
        cin>>price[i]>>level[i];
        level[i]--;//0開始
        int x;
        cin>>x;
        for(int j=0;j<x;j++){
            int v,p;
            cin>>v>>p;
            v--;
            edge[v][i]=p;//v到i的價格為p
        }
    }
}
int dijkstr(){
    for(int i=0;i<n;i++)d[i]=price[i];//把起點當作超級源點
    for(int i=0;i<n;i++){
        int temp=INF;
        int x;//最小點
        for(int j=0;j<n;j++)
            if(vis[j]&&d[j]<=temp)
                temp=d[x=j];
            vis[x]=0;//不再走
            for(int j=0;j<n;j++)
                if(d[x]+edge[x][j]<d[j]&&vis[j])
                    d[j]=d[x]+edge[x][j];
        }
    return d[0];//0
}
int main()
{
    cin>>m>>n;
    init();
    int ans=INF;
    for(int i=0;i<n;i++){
        int minLevel=level[i];//最小
        for(int j=0;j<n;j++){
            if(level[j]-minLevel>m||minLevel>level[j])
                vis[j]=0;//不可
            else vis[j]=1;
        }
        int cur=dijkstr();
       // cout<<cur<<endl;
        ans=min(ans,cur);
    }
    cout<<ans<<endl;
    return 0;
}

原本還有兩個題,一個題目太長了,看不下去了,一個大模擬的題,我就放棄了。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM