您的位置:首页 > 理论基础

2011年北京大学计算机研究生机试真题(题解)

2016-04-25 20:05 375 查看
九度OJ题目传送门:2011年北京大学计算机研究生机试真题

鸡兔同笼

题目描述

一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,每行一个正整数a (a < 32768)

输出

输出包含n行,每行对应一个输入,包含两个正整数,第一个是最少的动物数,第二个是最多的动物数,两个正整数用一个空格分开

如果没有满足要求的答案,则输出两个0。

样例输入

2

3

20

样例输出

0 0

5 10

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
int n, a;
scanf("%d", &n);
while(n--){
scanf("%d", &a);

int t1 = a/2;
int t2 = a/4;
int maxn = 0, minn = 0;
for(int i = 0; i <= t1; i++){
for(int j = 0; j <= t2; j++){
if(i*2+j*4==a){
if(minn==0)
minn = i+j;
if(i+j>maxn)
maxn = i+j;
if(i+j<minn)
minn = i+j;
}
}
}

printf("%d %d\n", minn, maxn);
}
return 0;
}

/**************************************************************
Problem: 1155
User: violet0908
Language: C++
Result: Accepted
Time:330 ms
Memory:1020 kb
****************************************************************/


放苹果

题目描述

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

输入

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

输出

对输入的每组数据M和N,用一行输出相应的K。

样例输入

1

7 3

样例输出

8

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int fun(int m, int n){
if(n == 1)
return 1;
if(m==1 || m==0)
return 1;
else if(m < 0)
return 0;
else
return fun(m, n-1)+fun(m-n, n);
}

int main()
{
int t, m, n;
scanf("%d", &t);
while(t--){
scanf("%d %d", &m, &n);
printf("%d\n", fun(m, n));
}
return 0;
}

/**************************************************************
Problem: 1160
User: violet0908
Language: C++
Result: Accepted
Time:0 ms
Memory:1020 kb
****************************************************************/


谁是你的潜在朋友

题目描述

“臭味相投”——这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着许多共同的兴趣。然而作为一个宅男,你发现自己与他人相互了解的机会并不太多。幸运的是,你意外得到了一份北大图书馆的图书借阅记录,于是你挑灯熬夜地编程,想从中发现潜在的朋友。

首先你对借阅记录进行了一番整理,把N个读者依次编号为1,2,…,N,把M本书依次编号为1,2,…,M。同时,按照“臭味相投”的原则,和你喜欢读同一本书的人,就是你的潜在朋友。你现在的任务是从这份借阅记录中计算出每个人有几个潜在朋友。

输入

每个案例第一行两个整数N,M,2 <= N ,M<= 200。接下来有N行,第i(i = 1,2,…,N)行每一行有一个数,表示读者i-1最喜欢的图书的编号P(1<=P<=M)

输出

每个案例包括N行,每行一个数,第i行的数表示读者i有几个潜在朋友。如果i和任何人都没有共同喜欢的书,则输出“BeiJu”(即悲剧,^ ^)

样例输入

4 5

2

3

2

1

样例输出

1

BeiJu

1

BeiJu

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int f[250];
int p[250];

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

for(int i = 0; i < n; i++){
scanf("%d", &p[i]);
f[p[i]]++;
}

for(int i = 0; i < n; i++){
if(f[p[i]]==1){
printf("BeiJu\n");
}
else if(f[p[i]]>1){
printf("%d\n", f[p[i]]-1);
}
}
}
return 0;
}

/**************************************************************
Problem: 1156
User: violet0908
Language: C++
Result: Accepted
Time:0 ms
Memory:1024 kb
****************************************************************/


中位数

题目描述

中位数定义:一组数据按从小到大的顺序依次排列,处在中间位置的一个数(或最中间两个数据的平均数).

给出一组无序整数,求出中位数,如果求最中间两个数的平均数,向下取整即可(不需要使用浮点数)

输入

该程序包含多组测试数据,每一组测试数据的第一行为N,代表该组测试数据包含的数据个数,1<=N<=10000.

接着N行为N个数据的输入,N=0时结束输入

输出

输出中位数,每一组测试数据输出一行

样例输入

4

10

30

20

40

3

40

30

50

4

1

2

3

4

0

样例输出

25

40

2

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
int n;
int num[10005];
while(scanf("%d", &n)!=EOF){
if(n==0)
break;

for(int i = 0; i < n; i++)
scanf("%d", &num[i]);

sort(num, num+n);
int ans;

if(n%2==1){
ans = num[n/2];
}
else{
ans = (num[n/2-1]+num[n/2])/2;
}
printf("%d\n", ans);
}
return 0;
}

/**************************************************************
Problem: 1157
User: violet0908
Language: C++
Result: Accepted
Time:20 ms
Memory:1020 kb
****************************************************************/


买房子

题目描述

某程序员开始工作,年薪N万,他希望在中关村公馆买一套60平米的房子,现在价格是200万,假设房子价格以每年百分之K增长,并且该程序员未来年薪不变,且不吃不喝,不用交税,每年所得N万全都积攒起来,问第几年能够买下这套房子(第一年房价200万,收入N万)

输入

有多行,每行两个整数N(10<=N<=50), K(1<=K<=20)

输出

针对每组数据,如果在第20年或者之前就能买下这套房子,则输出一个整数M,表示最早需要在第M年能买下,否则输出Impossible,输出需要换行

样例输入

50 10

40 10

40 8

样例输出

8

Impossible

10

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
double cnt, n, k, sum;
while(scanf("%lf %lf", &n, &k)!=EOF){
sum = n;
cnt = 1;
int fang = 200;

int flag = 1;

while(sum < fang){
fang = (1+k/100)*fang;
sum+=n;
cnt++;
if(cnt > 20){
printf("Impossible\n");
flag = 0;
break;
}
}
if(flag==1){
printf("%.0lf\n", cnt);
}
}
return 0;
}

/**************************************************************
Problem: 1158
User: violet0908
Language: C++
Result: Accepted
Time:0 ms
Memory:1020 kb
****************************************************************/


I Wanna Go Home

题目描述

The country is facing a terrible civil war—-cities in the country are divided into two parts supporting different leaders. As a merchant, Mr. M does not pay attention to politics but he actually knows the severe situation, and your task is to help him reach home as soon as possible.

“For the sake of safety,”, said Mr.M, “your route should contain at most 1 road which connects two cities of different camp.”

Would you please tell Mr. M at least how long will it take to reach his sweet home?

输入

The input contains multiple test cases.

The first line of each case is an integer N (2<=N<=600), representing the number of cities in the country.

The second line contains one integer M (0<=M<=10000), which is the number of roads.

The following M lines are the information of the roads. Each line contains three integers A, B and T, which means the road between city A and city B will cost time T. T is in the range of [1,500].

Next part contains N integers, which are either 1 or 2. The i-th integer shows the supporting leader of city i.

To simplify the problem, we assume that Mr. M starts from city 1 and his target is city 2. City 1 always supports leader 1 while city 2 is at the same side of leader 2.

Note that all roads are bidirectional and there is at most 1 road between two cities.

Input is ended with a case of N=0.

输出

For each test case, output one integer representing the minimum time to reach home.

If it is impossible to reach home according to Mr. M’s demands, output -1 instead.

样例输入

2

1

1 2 100

1 2

3

3

1 2 100

1 3 40

2 3 50

1 2 1

5

5

3 1 200

5 3 150

2 5 160

4 3 170

4 2 170

1 2 2 2 1

0

样例输出

100

90

540

思路:刚开始真想不出来,考虑的很复杂,最后参考了网上的题解后恍然大悟,对于不是同一个阵营的路换成单向的就简单了,同一个阵营的路还是双向路

#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0xffffff
#define MAXN 605
using namespace std;

int mp[MAXN][MAXN], dis[MAXN], team[MAXN];
bool vis[MAXN];

void dijkstra(int s, int n){
memset(vis, false, sizeof(vis));

for(int i = 1; i <= n; i++)
dis[i] = mp[s][i];

vis[s] = true;
dis[s] = 0;

for(int i = 1; i < n; i++){
int min = INF, pos;
for(int j = 1; j <= n; j++){
if(!vis[j] && dis[j] < min){
min = dis[j];
pos = j;
}
}

if(min == INF)
break;

vis[pos] = true;
for(int j = 1; j <= n; j++){
if(!vis[j] && dis[pos]+mp[pos][j] < dis[j]){
dis[j] = dis[pos] + mp[pos][j];
}
}
}
if(dis[2] < INF)
printf("%d\n", dis[2]);
else
printf("-1\n");
}

int main()
{
int n, m;
while(scanf("%d", &n)!=EOF){
if(n == 0)
break;

scanf("%d", &m);

for(int i = 0; i < MAXN; i++)
for(int j = 0; j < MAXN; j++)
mp[i][j] = INF;

for(int i = 0; i < m; i++){
int x, y, t;
scanf("%d %d %d", &x, &y, &t);
mp[x][y] = mp[y][x] = t;
}

for(int i = 1; i <= n; i++)
scanf("%d", &team[i]);

for(int i = 1; i<=n; i++){
for(int j = i+1; j <= n; j++){
if(team[i]==team[j])          //如果是同一个阵营,就不做操作
continue;
else if(team[i]==1 && team[j]==2)   //如果不是同一个阵营,就简历单向边
mp[j][i] = INF;
else if(team[i]==2 && team[j]==1)
mp[i][j] = INF;
}
}

dijkstra(1, n);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: