考研机试--浙大计算机研究生复试上机考试-2005年

A + B

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 21551    Accepted Submission(s): 12895


 

Problem Description
读入两个小于100的正整数A和B,计算A+B.
需要注意的是:A和B的每一位数字由对应的英文单词给出.
 

 

Input
测试输入包含若干测试用例,每个测试用例占一行,格式为"A + B =",相邻两字符串有一个空格间隔.当A和B同时为0时输入结束,相应的结果不要输出.
 

 

Output
对每个测试用例输出1行,即A+B的值.
 

 

Sample Input
 
one + two = three four + five six = zero seven + eight nine = zero + zero =
 

 

Sample Output
 

 把英语单词分别讨论处理,注意输入格式。

#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
string ch;
char c1[maxn],c2[maxn],c3[maxn],c4[maxn];
int ok(char c1[])
{
    int a=0;
    if(c1[0]=='o')
        a=1;
    else if(c1[0]=='e')
        a=8;
    else if(c1[0]=='n')
        a=9;
    else if(c1[0]=='z')
        a=0;
    else if(c1[0]=='t')
    {
        if(c1[1]=='w')
            a=2;
        else
            a=3;
    }
    else if(c1[0]=='f')
    {
        if(c1[1]=='o')
            a=4;
        else
            a=5;
    }
    else if(c1[0]=='s')
    {
        if(c1[1]=='i')
            a=6;
        else
            a=7;
    }
    return a;
}
int main()
{
    while(true)
    {
        getline(cin,ch);//read
        int len=ch.size();
        int i=0;
        int j1=0,j2=0,j3=0,j4=0;
        int f1=0,f11=0,f21=0;
        for(int i=0; i<len; i++)
        {
            //cout<<ch[i]<<endl;
            if(ch[i]=='=')break;
            if(ch[i]=='+')
            {
                f1=1;
                ++i;
                continue;
            }
            if(ch[i]==' '&&!f1)
            {
                f11=1;
                continue;
            }
            if(ch[i]==' '&&f1)
            {
                f21=1;
                continue;
            }
            if(f1)//+后面
            {
                if(!f21)
                {
                    c3[j3++]=ch[i];
                }
                else
                {
                    c4[j4++]=ch[i];
                }
            }
            else //+前面
            {
                if(!f11)
                {
                    c1[j1++]=ch[i];
                    //cout<<c1[j1]<<endl;
                }
                else
                {
                    c2[j2++]=ch[i];
                }
            }
        }
        int a=0,b=0,c=0,d=0;
        int s1=0,s2=0;
        if(j1&&j2)
        {
            a=ok(c1);
            b=ok(c2);
            s1=a*10+b;
        }
        else
        {
            a=ok(c1);
            s1=a;
        }
        if(j3&&j4)
        {
            c=ok(c3);
            d=ok(c4);
            s2=c*10+d;
        }
        else
        {
            c=ok(c3);
            s2=c;
        }
        if(a==0&&c==0)
            return 0;
        //cout<<s1<<" "<<s2<<endl;
        cout<<s1+s2<<endl;
    }
}
 

最大连续子序列

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 44756    Accepted Submission(s): 20452


 
Problem Description
给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ...,
Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,
例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和
为20。
在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该
子序列的第一个和最后一个元素。
 
 
Input
测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( < 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
 
 
Output
对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元
素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。
 
 
Sample Input
 
6 -2 11 -4 13 -5 -2 10 -10 1 2 3 4 -5 -23 3 7 -21 6 5 -8 3 2 5 0 1 10 3 -1 -5 -2 3 -1 0 -2 0
 
 
Sample Output
 
20 11 13 10 1 4 10 3 5 10 10 10 0 -1 -2 0 0 0
Hint
Hint

Huge input, scanf is recommended.

相当于一个简单的动态规划,当和s<0,更新s和左右端点为ai,当s>0时更新右端点为ai,当s>maxx时,更新左右答案。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 10000 + 66;
int a[maxn];
int main()
{
	int k;
	while (scanf("%d",&k)&&k)
	{
		for (int i = 1; i <= k; i++)
		{
			scanf("%d", &a[i]);
		}
		int s = 0;
		int maxx = -99999999;
		int l1 = 0, l2 = 0;
		int ansa = 0, ansb = 0;
		for (int i = 1; i <= k; i++)
		{
			if (s < 0)
			{
				s = a[i];
				l1 = a[i];
				l2 = a[i];
			}
			else
			{
				s += a[i];
				l2 = a[i];
			}

			if (s > maxx)
			{
				maxx = s;
				ansa = l1;
				ansb = l2;
			}
		}
		if(maxx>=0)
		printf("%d %d %d\n", maxx,ansa,ansb);
		else
		{
			printf("%d %d %d\n", 0, a[1], a[k]);
		}
	}
	//getchar();
	return 0;
}

畅通工程

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 85855    Accepted Submission(s): 45590


 
Problem Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
 
 
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
 
 
Output
对每个测试用例,在1行里输出最少还需要建设的道路数目。
 
 
Sample Input
 
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
 
 
Sample Output
 
1 0 2 998
Hint
Hint
Huge input, scanf is recommended.
 
 
Source
 
 
Recommend
JGShining
 
简单的并查集应用,利用并查集缩点之后,形成n个联通块,应该加上n-1条路。
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 10000 + 66;
int fa[maxn];
int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void init(int x, int y)
{
	int fx = find(x);
	int fy = find(y);
	if (fx != fy)
	{
		fa[fx] = fy;
	}
}
int main()
{
	int n,m;
	while (scanf("%d",&n)&&n)
	{
		for (int i = 1; i <= n; i++)fa[i] = i;
		scanf("%d", &m);
		while (m--)
		{
			int u, v;
			scanf("%d %d", &u, &v);
			init(u, v);
		}
		for (int i = 1; i <= n; i++)
		{
			find(i);
		}
		int ans = 0;
		for (int i = 1; i <= n; i++)
		{
			if (i == fa[i])ans++;
		}
		printf("%d\n", ans - 1);
	}
}

 

开门人和关门人

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 22975    Accepted Submission(s): 11504


 

Problem Description
每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签
到、签离记录,请根据记录找出当天开门和关门的人。
 

 

Input
测试输入的第一行给出记录的总天数N ( > 0 )。下面列出了N天的记录。
每天的记录在第一行给出记录的条目数M ( > 0 ),下面是M行,每行的格式为

证件号码 签到时间 签离时间

其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
 

 

Output
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。
注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前,
且没有多人同时签到或者签离的情况。
 

 

Sample Input
 
3 1 ME3021112225321 00:00:00 23:59:59 2 EE301218 08:05:35 20:56:35 MA301134 12:35:45 21:40:42 3 CS301111 15:30:28 17:00:10 SC3021234 08:00:00 11:25:25 CS301133 21:45:00 21:58:40
 

 

Sample Output
 
ME3021112225321 ME3021112225321 EE301218 MA301134 SC3021234 CS301133

 

考察结构体排序,注意读入,排两遍序之后输出即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 1000 + 66;
struct  student
{
    char name[20];
    int h, m, s;
    int h1, m1, s1;
} a[maxn];
bool cmp1(student a,student b)
{
    if (a.h < b.h)
        return true;
    else if (a.h > b.h)
        return false;
    else
    {
        if (a.m < b.m)
            return true;
        else if (a.m > b.m)
            return false;
        else
        {
            if (a.s < b.s)
                return true;
            else if (a.s > b.s)
                return false;
        }
    }
    return true;
}
bool cmp2(student a, student b)
{
    if (a.h1 < b.h1)
        return true;
    else if (a.h1 > b.h1)
        return false;
    else
    {
        if (a.m1 < b.m1)
            return true;
        else if (a.m1> b.m1)
            return false;
        else
        {
            if (a.s1 < b.s1)
                return true;
            else if (a.s1 > b.s1)
                return false;
        }
    }
    return true;
}
int main()
{
    int t;
    while (scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            int m;
            scanf("%d", &m);
            int m1=m;
            int id = 0;
            while (m1--)
            {
                scanf("%s", a[++id].name);
                scanf("%d:%d:%d ", &a[id].h, &a[id].m, &a[id].s);
                scanf("%d:%d:%d", &a[id].h1, &a[id].m1, &a[id].s1);
            }
            sort(a + 1, a+m + 1,cmp1);
            cout << a[1].name << " ";
            sort(a + 1, a + m + 1, cmp2);
            cout << a[m].name << endl;
        }
    }
}

排名

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 32662    Accepted Submission(s): 11974


 

Problem Description
今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑
每题的分值,所以并不是最后的排名。给定录取分数线,请你写程序找出最后通过分数线的
考生,并将他们的成绩按降序打印。
 

 

Input
测试输入包含若干场考试的信息。每场考试信息的第1行给出考生人数N ( 0 < N
< 1000 )、考题数M ( 0 < M < = 10 )、分数线(正整数)G;第2行排序给出第1题至第M题的正整数分值;以下N行,每行给出一
名考生的准考证号(长度不超过20的字符串)、该生解决的题目总数m、以及这m道题的题号
(题目号由1到M)。
当读入的考生人数为0时,输入结束,该场考试不予处理。
 

 

Output
对每场考试,首先在第1行输出不低于分数线的考生人数n,随后n行按分数从高
到低输出上线考生的考号与分数,其间用1空格分隔。若有多名考生分数相同,则按他们考
号的升序输出。
 

 

Sample Input
 
4 5 25 10 10 12 13 15 CS004 3 5 1 3 CS003 5 2 4 1 3 5 CS002 2 1 2 CS001 3 2 3 5 1 2 40 10 30 CS001 1 2 2 3 20 10 10 10 CS000000000000000001 0 CS000000000000000002 2 1 2 0
 

 

Sample Output
 
3 CS003 60 CS001 37 CS004 37 0 1 CS000000000000000002 20
 
考察结构体排序,排好序选择输出即可。

 

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
const int maxn = 1000 + 66;
int grade[maxn];
struct  student
{
	char name[maxn];
	int num;
	int grades;
}a[maxn];
bool cmp1(const student a, const student b)
{
	if (a.grades > b.grades)return true;
	else if (a.grades < b.grades)return false;
	else
	{
		return strcmp(a.name,b.name)<0;
	}
	return true;
}
int main()
{
	int n, m, g;
	while (scanf("%d %d %d", &n, &m, &g)&&n)
	{
		for (int i = 1; i <= m; i++)
		{
			scanf("%d", &grade[i]);
		}
		for (int i = 1; i <= n; i++)a[i].grades=0;
		int ans = 0;
		for (int i = 1; i <= n; i++)
		{
			scanf("%s %d", a[i].name, &a[i].num);
			for (int j = 1; j <= a[i].num; j++)
			{
				int id;
				scanf("%d", &id);
				a[i].grades += grade[id];
			}
			if (a[i].grades >= g)
			{
				ans++;
			}
		}
		printf("%d\n", ans);
		//cout << n << endl;
		sort(a + 1, a + n + 1, cmp1);
		for (int i = 1; i <= n; i++)
		{
			if (a[i].grades >= g)printf("%s %d\n", a[i].name, a[i].grades);
		}
	}
	return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值