2019年中南大学研究生复试机试题 题解

A:选球问题

http://39.106.164.46/problem.php?id=1208
思路:
从小到大排序即可,依次取满足题意的k个球。
AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 55
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,k,a[MAX];
char ch[MAX];

int main(){
    while(cin>>n>>k){
        for(int i=0;i<n;i++){
            cin>>ch[i];
            a[i]=ch[i]-'a'+1;
        }
        sort(a,a+n);
        int cnt=1,ans=a[0],tmp=a[0];
        for(int i=1;i<n;i++){
            if(cnt==k) break;
            if(a[i]>=tmp+2){
                ans+=a[i];
                cnt++;
                tmp=a[i];
            }
        }
        if(cnt!=k) cout<<-1<<endl;
        else cout<<ans<<endl;
    }

    return 0;
}

B:模拟出入栈游戏

http://39.106.164.46/problem.php?id=1209
题意:
按顺序压入a-z 26个字母,在栈顶的元素可以随时被取出,问给出的序列是否为一个合理的出栈序列。
思路:
依次判断前25个字母,若其后一个字母大于前一个字母,则合理;
若后一个字母小于前一个字母,就判断这两个字母间的所有字母是否都已出栈,若存在没有出栈的,则不合理,反之,则合理。
AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 30
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int a[MAX],b[MAX];
string s;

int main(){
   while(cin>>s){
       memset(a,0,sizeof(a));
       memset(b,0,sizeof(b));
       int len=s.length();
       bool flag=true;
       for(int i=0;i<len;i++){
           a[i]=s[i]-'a'+1;
       }
       for(int i=0;i<len-1;i++){
           if(a[i]>a[i+1]){
               for(int j=a[i+1]+1;j<a[i];j++){
                   if(b[j]==0){flag=false;break;}
               }
               if(!flag) break;
           }
           b[a[i]]=1;
       }
       if(flag) cout<<"yes"<<endl;
       else cout<<"no"<<endl;
   }
    return 0;
}

C:爬楼梯游戏

http://39.106.164.46/problem.php?id=1210
思路:
简单的递推。注意使用scanf读入数据。
代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 1000005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,dp[MAX];
int mod=1e9+7;

int main(){
   dp[1]=1,dp[2]=2;
   for(int i=3;i<=MAX;i++){
       dp[i]=(dp[i-1]+dp[i-2])%mod;
   }
   while(scanf("%d",&n)!=EOF){
       printf("%d\n",dp[n]);
   }
    return 0;
}

D:小镇购物

http://39.106.164.46/problem.php?id=1211
思路:
多源BFS。题目求的是从每个商店出发购买s种物品的代价。但如果每个商店都进行一遍BFS,n太大会超时。由于k<=100,可以换个思考方式,对物品进行BFS,我们可以求出从第i个商店出发购买第j种物品所花费的最小代价。ans[MAX][105]代表第i个商店到第j种商品的最近距离,既做标记数组又做计数数组。最后只需对ans[i]进行排序,取前s种花费最小的商品即可。
代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 100005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m,k,s;
int shop[MAX],ans[MAX][105];//ans[i][j]代表第i个商店到第j种商品的最近距离,既做标记数组又做计数数组

vector<int> adj[MAX];

void bfs(int id){ //id为商品编号
    queue<int> q;
    for(int i=1;i<=n;i++){
        if(shop[i]==id){
            //如果该商店的物品就是要搜索的物品则代价为0
            ans[i][id]=0;
            //从拥有该物品的商店开始搜索
            q.push(i);
        }
    }
    while(!q.empty()){
        int top=q.front();
        q.pop();
        for(int i=0;i<adj[top].size();i++){
            int nxt=adj[top][i]; //现在搜索到的商店编号
            if(ans[nxt][id]==-1){
                //该商店还没被搜索到, 则购买index物品的代价为上一步的代价+1
                ans[nxt][id]=ans[top][id]+1;
                q.push(nxt);
            }
        }
    }
}


int main(){
    while(scanf("%d %d %d %d",&n,&m,&k,&s)!=EOF){
        for(int i=1;i<=n;i++){
            scanf("%d",&shop[i]);
        }
        int a,b;
        for(int i=0;i<m;i++){
            scanf("%d %d",&a,&b);
            adj[a].push_back(b);
            adj[b].push_back(a);
        }
        memset(ans,-1,sizeof(ans)); //初始化-1
        for(int i=1;i<=k;i++){
            bfs(i);
        }
        for(int i=1;i<=n;i++){
            int res=0;
            //我们把第i个商店购买各个物品所需要的代价排序
            //我们存数据的时候是从1开始的所以要加1
            sort(ans[i]+1,ans[i]+1+k);
            //从中挑选代价最小的s个物品
            for(int j=1;j<=s;j++)
                res+=ans[i][j];
            printf("%d ",res);
        }

        printf("\n");
        for(int i=1;i<=n;i++){
            adj[i].clear();
        }
    }
    return 0;
}

E:graph’s connected components

http://39.106.164.46/problem.php?id=1212
题意:
给出m个数,其中任意的x和y,若 x (按位与)y = 0,则x和y是相邻的,求形成的图中总共的连通分量的个数。
思路:
感觉像是并查集,可还是wa了 qwq。。。。求正解
首先,若存在0,则连通分量就是1
若不存在0,可以先找出满足2的次方的最大数,所有小于这个数的都和这个数在一个集合中
然后若两个数相加的和为2的x次方-1,则这两个数也在一个集合中
代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5000005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m;
int a[MAX],b[MAX],fa[MAX],flag[MAX];

int findfather(int x){
    if(x==fa[x]) return fa[x];
    else return fa[x]=findfather(fa[x]);
}

void _union(int a,int b){
    int aa=findfather(a);
    int bb=findfather(b);
    if(aa!=bb){
        fa[aa]=bb;
    }
}

int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        memset(flag,0,sizeof(flag));
        memset(b,0,sizeof(b));

        bool f=true;
        for(int i=0;i<m;i++){
            scanf("%d",&a[i]);
            if(a[i]==0){
                f=false;
            }
        }
        if(!f){
            printf("1\n");
            continue;
        }
        sort(a,a+m);
        for(int i=0;i<m;i++){
            b[a[i]]=i;
            flag[a[i]]=1;
        }
        for(int i=0;i<MAX;i++){
            fa[i]=i;
        }
        int t=2,maxl=-1,index=-1;
        while(t<=n){
            if(flag[t]==1){
                maxl=max(maxl,t);
                index=b[t];
            }
            t*=2;
        }
        for(int i=0;i<index;i++){
            _union(i,index);
        }
        for(int i=max(0,index);i<m;i++){
            for(int j=1;j<=n;j++){
                int tmp=(int)pow(2,j)-a[i]-1;
                if(tmp>=0&&flag[tmp]==1&&findfather(i)!=findfather(b[tmp])){
                    _union(i,b[tmp]);
                }
            }
            int t=a[i]*2,maxl=(int)pow(2,n);
            while(t<=maxl){
                if(flag[t]==1){
                    _union(i,b[t]);
                }
                t*=2;
            }
        }
        int cnt=0;
        for(int i=0;i<m;i++){
            if(fa[i]==i) cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
}

你可能感兴趣的:(机试)