2013年中南大学计算机研究生复试机试题解

高温假闲着无聊,在voj上把CSU的机试题 刷了一道,可能是因为题目年代比较久远,题目的难度并不是很大。稍稍整理一下,希望以后用得着。

1264: 惠民工程

所有题目中唯一的数据结构题
一道最小生成树(MST)的模板题
MST问题的解法:Prim,Kruskal等

传送门

Description
市政府“惠民工程”的目标是在全市n个居民点间之架设煤气管道(但不一定有直接的管道相连,只要能间接通过管道可达即可)。很显然最多可架设 n(n-1)/2条管道,然而实际上要连通n个居民点只需架设n-1条管道就可以了。现请你编写程序,计算出该惠民工程需要的最低成本。

Input
测试输入包含若干测试用例。每个测试用例的第1行给出居民点数目M ( < =100 )、 评估的管道条数 N;随后的 N 行对应居民点间管道的成本,每行给出一对正整数,分别是两个居民点的编号,以及此两居民点间管道的成本(也是正整数)。为简单起见,居民点从1到M编号。

Output
对每个测试用例,在1行里输出全市管道畅通所需要的最低成本。若统计数据不足以保证畅通,则输出“?”。

Sample Input
3 3
1 2 1
1 3 2
2 3 4
3 1
2 3 2
Sample Output
3
?
Prim代码:

#include <stdio.h>
#define INF 0x7ffff
#define MAXVER 128

typedef struct graph
{
    int adjMatrix[MAXVER][MAXVER];
    int weight[MAXVER];
    int vis[MAXVER];
} graph;

graph Graph;
int m,n;

void init()
{
    for(int i=0; i<MAXVER; i++)
    {
        Graph.vis[i] = 0;
        for(int j=0; j<MAXVER; j++)
            if(i==j)
                Graph.adjMatrix[i][j] = 0;
            else
                Graph.adjMatrix[i][j] = INF;
    }
}

int prim()
{
    int ans = 0;
    for(int i=1; i<=m; i++)
        Graph.weight[i] = Graph.adjMatrix[1][i];
    Graph.vis[1] = 1;
    for(int i=2; i<=m; i++)
    {
        int minCost = INF,idx;
        for(int j=1; j<=m; j++)
            if(!Graph.vis[j]&&minCost>Graph.weight[j])
            {
                minCost = Graph.weight[j];
                idx = j;
            }
        if(minCost==INF)
            return -1;
        Graph.vis[idx] = 1;
        ans+=Graph.weight[idx];
        for(int j=1; j<=m; j++)
            if(!Graph.vis[j]&&Graph.weight[j]>Graph.adjMatrix[idx][j])
                Graph.weight[j] = Graph.adjMatrix[idx][j];
    }
    return ans;
}

int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        init();
        for(int i=0; i<n; i++)
        {
            int src,dest,weight;
            scanf("%d%d%d",&src,&dest,&weight);
            Graph.adjMatrix[src][dest] = Graph.adjMatrix[dest][src] = weight;
        }
        int ans = prim();
        (ans==-1)?printf("?\n"):printf("%d\n",ans);
    }
    return 0;
}

Kruskal代码:

#include <stdio.h>
#include <algorithm>
#define MAXVER 4096

int uSet[MAXVER];
int sum,ans;

struct edge
{
    int src,dest,weight;
};
edge graph[MAXVER];

int cmp(edge a,edge b)
{
    return a.weight<b.weight;
}

void MakeSet(int m)
{
    for(int i=1; i<=m; i++)
        uSet[i] = i;
}

int Find(int key)
{
    if(key!=uSet[key])
        key = Find(uSet[key]);
    return key;
}

void Union(edge e)
{
    if(Find(e.src)!=Find(e.dest))
    {
        uSet[Find(e.src)] = Find(e.dest);
        sum++;
        ans+=e.weight;
    }
}

void Kruskal(int n)
{
    sort(graph+1,graph+n+1,cmp);
    for(int i=1; i<=n; i++)
        Union(graph[i]);
}

int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n))
    {
        ans = sum = 0;
        MakeSet(m);
        for(int i=1; i<=n; i++)
            scanf("%d%d%d",&graph[i].src,&graph[i].dest,&graph[i].weight);
        Kruskal(n);
        sum==m-1?printf("%d\n",ans):printf("?\n");
    }
    return 0;
}

1263: 最少钱币数

暴力枚举

传送门

Description
作为A公司的职员,最盼望的日子就是每月的8号了,因为这一天是发工资的日子,养家糊口就靠它了。但是对于公司财务处的工作人员来说,这一天则是很忙碌的一天,财务处的小胡最近就在考虑一个问题:如果每个员工的工资额都知道,最少需要准备多少张人民币,才能在给每位职员发工资的时候都不用老师找零呢?这里假设员工的工资都是正整数,单位元,人民币一共有100元、50元、10元、5元、2元和1元六种。

Input
输入数据包含多个测试实例,每个测试实例的第一行是一个整数n(n<100),表示老师的人数,然后是n个老师的工资(工资<5000)。

Output
每个测试用例输出一行,即凑成钱数值M最少需要的钱币个数。如果凑钱失败,输出“Impossible”。你可以假设,每种待凑钱币的数量是无限多的。

Sample Input
3
1 2 3
2
1 2
Sample Output
4
2
代码:

#include <stdio.h>
int main()
{
    int money[6]= {100,50,10,5,2,1},n;
    while(~scanf("%d",&n))
    {
        int ans = 0,salary = 0;
        while(n--)
        {
            scanf("%d",&salary);
            for(int i=0; i<6; i++)
                if(salary/money[i])
                    ans+=salary/money[i],salary%=money[i];
        }
        printf("%d\n",ans);
    }
    return 0;
}

1262: 安全密码

按题目要求模拟就完事了~

传送门

Description
网络上各类交易活动越来越普及,为了能够安安心心地上网,经常需要设置一个安全的密码。一般来说一个比较安全的密码至少应该满足下面两个条件:
(1)密码长度大于等于8。
(2)密码中的字符应该来自下面“字符类别”中四组中的至少三组。
这四个字符类别分别为:
(1)大写字母:A,B,C…Z;
(2)小写字母:a,b,c…z;
(3)数字:0,1,2…9;
(4)特殊符号:~,!,@,#,$,%,^;
给你一个密码,你的任务就是判断它是不是一个安全的密码。

Input
输入数据有多组,每组占一行,每行一个密码(长度最大可能为50),密码仅包括上面的四类字符。

Output
对于每个测试实例,判断这个密码是不是一个安全的密码,是的话输出YES,否则输出NO。

Sample Input
a1b2c3d4
Linle@ACM
^~^@^@!%
Sample Output
NO
YES
NO
代码:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main()
{
    char psw[99];
    while(~scanf("%s",psw))
    {
        int len = strlen(psw);
        if(len<8)
        {
            printf("NO\n");
            continue;
        }
        int k1,k2,k3,k4;
        k1 = k2 = k3 = k4 = 0;
        for(int i=0; i<len; i++)
        {
            if(psw[i]>='A'&&psw[i]<='Z')
                k1 = 1;
            else if(psw[i]>='a'&&psw[i]<='z')
                k2 = 1;
            else if(psw[i]>='0'&&psw[i]<='9')
                k3 = 1;
            else
                k4 = 1;
        }
        if(k1+k2+k3+k4>=3)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

1261: 水仙花数

初中的时候觉得这题好难( ̄▽ ̄)”
其实不要想太复杂就能做出
没思路的多半是想太多了
翻出了自己去年的AC代码作为反例奉劝大家想问题不要太复杂

传送门

Description
春天是鲜花灿烂的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3。现在要求输出所有在m和n范围内的水仙花数。

Input
输入数据有多组,每组占一行,包括两个整数m和n(100<=m<=n<=999)。

Output
对于每个测试实例,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开(注意每组输出的最后一个数之后不要加空格);如果给定的范围内不存在水仙花数,则输出no;每个测试实例的输出占一行。

Sample Input
100 120
300 380
Sample Output
no
370 371

去年代码(自己给自己加难度作死):

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int n,m,x,y,z,sum;
    vector<int> ans;
    while(cin>>m>>n)
    {
        sum=0;
        ans.clear();
        for(int i=m; i<=n; i++)
        {
            x=i/100;
            y=(i/10)%10;
            z=i%10;
            if((x*x*x)+(y*y*y)+(z*z*z)==i)
            {
                sum++;
                ans.push_back(i);
            }
        }
        if(sum==0)
            cout<<"no";
        for(vector<int>::iterator it=ans.begin(); it!=ans.end(); it++)
        {
            if(it!=ans.end())
                cout<<*it<<" ";
            else
                cout<<*it;
        }
        cout<<endl;

    }
    return 0;
}

今年代码:

#include <stdio.h>
int main()
{
    int i,j,k,m,n;
    while(~scanf("%d%d",&m,&n))
    {
        int ans[99];
        for(i=m,j=0; i<=n; i++)
        {
            int a,b,c;
            a = i/100;
            b = (i/10)%10;
            c = i%10;
            if(a*a*a+b*b*b+c*c*c==i)
                ans[j++] = i;
        }
        if(j!=0)
        {
            for(int k=0; k<j-1; k++)
                printf("%d ",ans[k]);
            printf("%d\n",ans[j-1]);
        }
        else
            printf("no\n");
    }
    return 0;
}

1260: 回文串问题

基本的字符串操作
暴力即可

传送门

Description
“回文串”是一个正读和反读都一样的字符串,字符串由数字和小写字母组成,比如“level”或者“abcdcba”等等就是回文串。请写一个程序判断读入的字符串是否是“回文”。

Input
输入包含多个测试实例,每一行对应一个字符串,串长最多100字母。

Output
对每个字符串,输出它是第几个,如第一个输出为”case1:”;如果一个字符串是回文串,则输出”yes”,否则输出”no”,在yes/no之前用一个空格。

Sample Input
level
abcde
noon
haha
Sample Output
case1: yes
case2: no
case3: yes
case4: no
代码:

#include <stdio.h>
#include <string.h>
int main()
{
    char str[128],cnt = 0;
    while(~scanf("%s",str))
    {
        int len = strlen(str),flag = 1;
        for(int i=0; i<len/2; i++)
            if(str[i]!=str[len-i-1])
                flag = 0;
        printf("case%d: %s\n",++cnt,flag?"yes":"no");
    }
    return 0;
}

总结

除了第一题属于数据结构内容以外,其他的都是C程序设计难度,所以编码的熟练度要求较高,第一题DeBug了很久才AC,如果放在考场上会很影响心态(T_T),这道MST其实只是个模板题理应一次AC,以后还是要多加练习啊…

猜你喜欢

转载自blog.csdn.net/tilmant/article/details/81365168