天梯赛赛前训练

目录

L2-1 包装机 (25 分)

题目描述

一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。
在这里插入图片描述
在这里插入图片描述

图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态

一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。

现给定一系列按钮操作,请你依次列出流水线上的物品。

输入格式:

输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 S​max(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。

最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。

输出格式:
在一行中顺序输出流水线上的物品,不得有任何空格。

输入样例:

3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1
1
2
3
4
5
输出样例:

MATA

题目代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<double,double> P;
const ll maxn=1e6+10;
ll n,m,val;
ll a[maxn];
ll b[maxn];
char s[110][1010];
char str[1010];
ll cnt;
int main(){
    
    
    cin>>n>>m>>val;
    for(int i=1;i<=n;i++){
    
    
        cin>>s[i];
        a[i]=m;
    }
    ll k;
    while(cin>>k){
    
    
        if(k==-1)break;
        if(k!=0){
    
    
            if(b[k]>=m)continue;
            if(cnt<val){
    
    
                cnt++;
                str[cnt]=s[k][b[k]];
                b[k]++;
           }else{
    
    
                cout<<str[cnt];
                cnt--;
                cnt++;
                str[cnt]=s[k][b[k]];
                b[k]++;

           }
        }else{
    
    
            if(!cnt)continue;
            cout<<str[cnt];
            cnt--;
        }
        //cout<<(str+1)<<endl;
    }
    return 0;
}

L2-2 病毒溯源 (25 分)

题目描述

病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。

扫描二维码关注公众号,回复: 13968247 查看本文章

现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。

在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。

输入格式:
输入在第一行中给出一个正整数 N(≤10
4
),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。

随后 N 行,每行按以下格式描述一种病毒的变异情况:

k 变异株1 …… 变异株k
其中 k 是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。

输出格式:
首先输出从源头开始最长变异链的长度。

在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。

输入样例:
10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1
输出样例:
4
0 4 9 1

题目代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<double,double> P;
const ll maxn=1e6+10;
ll n;
ll ma=-1;
vector<ll> g[maxn];
ll vis[maxn];
ll pre[maxn],num[maxn],b[maxn];
ll cnt=0;
ll ans[maxn],ans1[maxn];
void dfs(ll x){
    
    
    for(int i=0;i<g[x].size();i++){
    
    
        ll v=g[x][i];
        num[v]=num[x]+1;
        ma=max(num[v]+1,ma);
        pre[v]=x;
        dfs(v);
    }
    return ;
}
int main(){
    
    
    cin>>n;
    for(int i=0;i<n;i++){
    
    
        ll k;
        cin>>k;
        for(int j=1;j<=k;j++){
    
    
            ll x;
            cin>>x;
            g[i].push_back(x);
            vis[x]=1;
        }
    }
    for(int i=0;i<n;i++){
    
    
        pre[i]=-1;
    }
    for(int i=0;i<n;i++){
    
    
        if(!vis[i]){
    
    
            dfs(i);
        }
    }
    for(int i=0;i<=ma;i++){
    
    
        ans[i]=n;
    }
    ll root=-1;
    ll flag=-1;
    for(int i=0;i<n;i++){
    
    
        if((ma-1)==num[i]){
    
    
            root=i;
            cnt=0;
            cnt++;
            b[cnt]=root;
            while(1){
    
    
                root=pre[root];
                if(root==-1)break;
                cnt++;
                b[cnt]=root;
            }
            flag=0;
            for(int j=cnt;j>=1;j--){
    
    
                if(b[j]==ans[j])continue;
                if(ans[j]>b[j]){
    
    
                    flag=1;
                    break;
                }else{
    
    
                    flag=0;
                    break;
                }
            }
            if(flag){
    
    
                for(int j=cnt;j>=1;j--){
    
    
                    ans[j]=b[j];
                }
            }
        }
    }
    if(ma!=-1)cout<<ma<<endl;
    else{
    
    
        cout<<"1"<<endl;
    }
    for(int j=ma;j>1;j--){
    
    
        cout<<ans[j]<<" ";
    }
    cout<<ans[1];
    return 0;
}

L2-039 清点代码库 (25 分)

题目描述

这里我们把问题简化一下:首先假设两个功能模块如果接受同样的输入,总是给出同样的输出,则它们就是功能重复的;其次我们把每个模块的输出都简化为一个整数(在 int 范围内)。于是我们可以设计一系列输入,检查所有功能模块的对应输出,从而查出功能重复的代码。你的任务就是设计并实现这个简化问题的解决方案。

输入格式:
输入在第一行中给出 2 个正整数,依次为 N(≤10
4
)和 M(≤10
2
),对应功能模块的个数和系列测试输入的个数。

随后 N 行,每行给出一个功能模块的 M 个对应输出,数字间以空格分隔。

输出格式:
首先在第一行输出不同功能的个数 K。随后 K 行,每行给出具有这个功能的模块的个数,以及这个功能的对应输出。数字间以 1 个空格分隔,行首尾不得有多余空格。输出首先按模块个数非递增顺序,如果有并列,则按输出序列的递增序给出。

题目代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<double,double> P;
const ll maxn=1e6+10;
ll n,m;
map<vector<ll>,ll> mp;
struct node{
    
    
    vector<ll> v;
    ll ct;
    bool operator<(const node &rh)const{
    
    
        if(ct==rh.ct)return v<rh.v;
        return ct>rh.ct;
    }
};
vector<node> ans;
int main(){
    
    
    cin>>n>>m;
    while(n--){
    
    
        vector<ll> v;
        for(int i=0;i<m;i++){
    
    
            ll num;
            cin>>num;
            v.push_back(num);
        }
        mp[v]++;
    }
    cout<<mp.size()<<endl;
    for(auto i:mp){
    
    
        node no;
        no.ct=i.second;
        no.v=i.first;
        ans.push_back(no);
    }
    sort(ans.begin(),ans.end());
    for(auto i:ans){
    
    
        cout<<i.ct;
        for(auto j:i.v){
    
    
            cout<<" "<<j;
        }
        cout<<endl;
    }
    return 0;
}

L2-4 哲哲打游戏 (25 分)

题目描述

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市,哲哲自然要快速攻略游戏,守护硬核游戏玩家的一切!

为简化模型,我们不妨假设游戏有 N 个剧情点,通过游戏里不同的操作或选择可以从某个剧情点去往另外一个剧情点。此外,游戏还设置了一些存档,在某个剧情点可以将玩家的游戏进度保存在一个档位上,读取存档后可以回到剧情点,重新进行操作或者选择,到达不同的剧情点。

为了追踪硬核游戏玩家哲哲的攻略进度,你打算写一个程序来完成这个工作。假设你已经知道了游戏的全部剧情点和流程,以及哲哲的游戏操作,请你输出哲哲的游戏进度。

输入格式:
输入第一行是两个正整数 N 和 M (1≤N,M≤10^5),表示总共有 N 个剧情点,哲哲有 M 个游戏操作。

接下来的 N 行,每行对应一个剧情点的发展设定。第 i 行的第一个数字是 K​i​​ ,表示剧情点 i 通过一些操作或选择能去往下面 K​i个剧情点;接下来有 K​i个数字,第 k 个数字表示做第 k 个操作或选择可以去往的剧情点编号。

最后有 M 行,每行第一个数字是 0、1 或 2,分别表示:

0 表示哲哲做出了某个操作或选择,后面紧接着一个数字 j,表示哲哲在当前剧情点做出了第 j 个选择。我们保证哲哲的选择永远是合法的。
1 表示哲哲进行了一次存档,后面紧接着是一个数字 j,表示存档放在了第 j 个档位上。
2 表示哲哲进行了一次读取存档的操作,后面紧接着是一个数字 j,表示读取了放在第 j 个位置的存档。
约定:所有操作或选择以及剧情点编号都从 1 号开始。存档的档位不超过 100 个,编号也从 1 开始。游戏默认从 1 号剧情点开始。总的选项数(即 ∑K​i)不超过 10^​6​​ 。

输出格式:
对于每个 1(即存档)操作,在一行中输出存档的剧情点编号。

最后一行输出哲哲最后到达的剧情点编号。

输入样例:
10 11
3 2 3 4
1 6
3 4 7 5
1 3
1 9
2 3 5
3 1 8 5
1 9
2 8 10
0
1 1
0 3
0 1
1 2
0 2
0 2
2 2
0 3
0 1
1 1
0 2
输出样例:
1
3
9
10
样例解释:
简单给出样例中经过的剧情点顺序:

1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10。

档位 1 开始存的是 1 号剧情点;档位 2 存的是 3 号剧情点;档位 1 后来又存了 9 号剧情点。

题目代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<double,double> P;
const ll maxn=1e6+10;

ll n,m;
ll q[maxn],p[maxn];
ll b[maxn],sum[maxn];
ll cnt1=0;
int main(){
    
    
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    
    
        ll k;
        scanf("%lld",&k);
        sum[i]=sum[i-1]+k;
        for(int j=1;j<=k;j++){
    
    
            ll x;
            scanf("%lld",&x);
            cnt1++;
            p[cnt1]=x;
        }
    }
    ll cnt=1;
    b[cnt]=1;
    while(m--){
    
    
        ll op,val;
        scanf("%lld%lld",&op,&val);
        if(op==0){
    
    
            ll id=b[cnt];
            id=sum[id-1]+val;
            cnt++;
            b[cnt]=p[id];
        }else if(op==1){
    
    
            q[val]=b[cnt];
            printf("%lld\n",q[val]);
        }else{
    
    
            cnt=1;
            b[cnt]=q[val];
        }
    }
    printf("%lld",b[cnt]);
    return 0;
}

结语


“遇事不决可问春风,春风不语即随本心”的意思是:对一件事犹豫不决,就问春风该如何做,春风给不出答案,就凭自己本心做出决断。“遇事不决可问春风,春风不语即随本心”一句出自网络作家“烽火戏诸侯”的《剑来》,其原文是:“遇事不决,可问春风。春风不语,遵循己心”。

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/weixin_46627433/article/details/124221579