浙江大学2011年复试上机题 解题报告

有一周多没更新了 最近蹭课效果喜人 谌老师的操作系统课 很具有启发性 也喜欢给大家提问题 大家可以在座位上直接回答 不必站起来和举手 我第一次去听 就回答了四五个问题 感觉很过瘾 精神一直很振奋 高中的课堂就是这种感觉 可惜大学的课堂尤其数学等课程往往不给你回答题目的机会 我挺不喜欢这种一直坐在底下默默听的感觉 邓老师的数据结构课就更是非常好了 每次都收获很大 组成原理的课收获也不小 感觉比自己看书要快很多 而网络课就相对乏味了 可能是还没进入核心部分的原因?也可能是老师真的就这风格 而且我还不知道老师的姓名呢 都不方便问身边的同学其他老师的上课时间和地点 这个比较悲催

===============================================

九度OJ 题目1001:A+B for Matrices

时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:3347  解决:1429
题目描述:
        This time, you are supposed to find A+B where A and B are two matrices, and then count the number of zero rows and columns.
输入:
        The input consists of several test cases, each starts with a pair of positive integers M and N (≤10) which are the number of rows and columns of the matrices, respectively. Then 2*M lines follow, each contains N integers in [-100, 100], separated by a space. The first M lines correspond to the elements of A and the second M lines to that of B.
        The input is terminated by a zero M and that case must NOT be processed.
输出:
        For each test case you should output in one line the total number of zero rows and columns of A+B.
样例输入:
    2 2
    1 1
    1 1
    -1 -1
    10 9
    2 3
    1 2 3
    4 5 6
    -1 -2 -3
    -4 -5 -6
    0
样例输出:
    1
    5
#include <iostream>
#include <fstream>
using namespace std;
#define N 10
int a[N][N], b[N][N], c[N][N];

int main()
{
	int i, j, k, n, m;
	ifstream cin("ZJU_1001.txt");//
	while( cin >> m >> n ){
		for( i=0; i<m; i++ )
			for( j=0; j<n; j++ )
				cin >> a[i][j];
		for( i=0; i<m; i++ )
			for( j=0; j<n; j++ ){
				cin >> b[i][j];
				c[i][j] = a[i][j] + b[i][j];
			}

		int row, column,count=0;
		for( i=0; i<m; i++ ){
			row = 0;
			for( j=0; j<n; j++ ){	
				if( c[i][j] == 0 )
					row++;
				else break;
			}
			if( row == n )
				count++;
		}

		for( j=0; j<n; j++ ){
			column = 0;
			for( i=0; i<m; i++ ){	
				if( c[i][j] == 0 )
					column++;
				else break;
			}
			if( column == m )
				count++;
		}

		cout << count << endl;
	}
	system("pause");//
	return 0;
}


九度OJ 题目1002:Grading
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:3570  解决:867
题目描述:
        Grading hundreds of thousands of Graduate Entrance Exams is a hard work. It is even harder to design a process to make the results as fair as possible. One way is to assign each exam problem to 3 independent experts. If they do not agree to each other, a judge is invited to make the final decision. Now you are asked to write a program to help this process.
        For each problem, there is a full-mark P and a tolerance T(<P) given. The grading rules are:
        ? A problem will first be assigned to 2 experts, to obtain G1 and G2. If the difference is within the tolerance, that is, if |G1 - G2| ≤ T, this problem's grade will be the average of G1 and G2.
        ? If the difference exceeds T, the 3rd expert will give G3.
        ? If G3 is within the tolerance with either G1 or G2, but NOT both, then this problem's grade will be the average of G3 and the closest grade.
        ? If G3 is within the tolerance with both G1 and G2, then this problem's grade will be the maximum of the three grades.
        ? If G3 is within the tolerance with neither G1 nor G2, a judge will give the final grade GJ.
输入:
        Each input file may contain more than one test case.
        Each case occupies a line containing six positive integers: P, T, G1, G2, G3, and GJ, as described in the problem. It is guaranteed that all the grades are valid, that is, in the interval [0, P].
输出:
        For each test case you should output the final grade of the problem in a line. The answer must be accurate to 1 decimal place.
样例输入:
    20 2 15 13 10 18
样例输出:
    14.0
#include <iostream>
#include <cmath>
#include <fstream>
using namespace std;
int t;

float withinT( int x, int y ){
	if( abs(1.0*(x-y)) <= t )
		return 0.5*(x+y);
	else return 0;
}

int main()
{
	int i, j, k, n, m;
	int g1, g2, g3, gj, p;
	float a;
	cout.setf(ios::fixed);
	cout.setf(ios::showpoint);
	cout.precision(1);
	ifstream cin("ZJU_1002.txt");//
	while( cin >> p >> t >> g1 >> g2 >> g3 >> gj ){

		float g13, g12, g23;
		g12 = withinT(g1,g2);
		if( g12!=0 )
			a = g12;

		else {
			g13 = withinT(g1,g3);
			g23 = withinT(g2,g3);

			if( g13!=0 ){
				if( g23==0 )
					a = g13;
				else a = max(g1,max(g2,g3));
			}
			else if( g23!=0 )
				a = g23;
			else a = gj;
		}
		cout << a << endl;
	}
	system("pause");
	return 0;
}


九度OJ 题目1004:Median
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:3008  解决:779
题目描述:
        Given an increasing sequence S of N integers, the median is the number at the middle position. For example, the median of S1={11, 12, 13, 14} is 12, and the median of S2={9, 10, 15, 16, 17} is 15. The median of two sequences is defined to be the median of the non-decreasing sequence which contains all the elements of both sequences. For example, the median of S1 and S2 is 13.
        Given two increasing sequences of integers, you are asked to find their median.
输入:
        Each input file may contain more than one test case.
        Each case occupies 2 lines, each gives the information of a sequence. For each sequence, the first positive integer N (≤1000000) is the size of that sequence. Then N integers follow, separated by a space.
        It is guaranteed that all the integers are in the range of long int.
输出:
        For each test case you should output the median of the two given sequences in a line.
样例输入:
    4 11 12 13 14
    5 9 10 15 16 17
样例输出:
    13

这道题有点难度 其实就是11年考研数据结构编程题目的延伸——原题是两个长度相等的升序序列 本题的长度不一定相等

我的思路仍是考研原题的思路 并对其做了普适性的扩展:设较短的序列为a 长序列为b a的中位数的下标为mid 则用a[mid]去比较b[mid]和b[-mid](即倒数第mid个元素 仿python语法) 若a[mid]<=b[mid]则舍掉a[mid]之前的元素和b的最后mid-1个元素; 若a[mid]>=b[-mid]则舍掉a[mid]之后的元素和b的前mid-1个元素; 若以上两种情况都不满足即a[mid]>b[mid]则舍掉b的前后各mid-1个元素。 当b序列短于a序列时 再交换两者保证a总是更短的序列(含相等情况) 证明上述三种舍弃元素行为的正确性还是比较简单的 只需说明舍弃的元素中不含中位数 或者说中位数的下标不在舍弃元素可能存在的下标区间即可 暂不详述了

经过以上处理后 从while循环出来时 a元素只有2个 b则>=2个 之后再对a处理 使之只剩下一个 当a只有一个元素时 通过与b当下的中位数比较即可方便的确定公共序列的真正的中位数

我的思路的缺点之一 是while出口时a是2个元素而不是1个 如果能在while中让a只剩1个元素 则代码可以更简洁 留作以后优化吧

另外本程序中嵌入了一个用来生成1~100并随机分给a和b的调试代码 方便调试发现错误 开始提交时WA但又找不到错在哪里 后来经由这段调试代码很快发现是last round处应为3个可能分支 只考虑了前两种

#include <cstdio>
#include <ctime>
#include <iostream>
using namespace std;
#define N 1000000
int a[N], b[N], result;

void swap( int &x, int &y ){	//swap要用引用符
	int temp = x;
	x = y; y = temp;
}

void test( int* x, int* y, int s1, int e1, int s2, int e2 ){
	int i;	
	for( i=s1; i<=e1; i++ )
		printf("%d ",x[i]);
	printf("\n");
	for( i=s2; i<=e2; i++ )
		printf("%d ",y[i]);
	printf("\n\n");
}

int she( int* x, int* y, int s1, int e1, int s2, int e2 ){	//xlen<ylen
	int i, j, k, mid, slen, flag1, flag2, result;	//slen=she's length
	while( e1 - s1 > 1 ){
		//test(x,y,s1,e1,s2,e2);//

		mid = (s1+e1)/2;
		slen = (e1-s1)/2;	//x为奇数个
		flag1 = s2 + slen;
		flag2 = e2 - slen;
		if( x[mid] <= y[flag1] ){	//x前半<=y前半
			s1 += slen;
			e2 -= slen;
		}else if( x[mid] >= y[flag2] ){ //x后半>=y后半
			e1 -= slen;
			s2 += slen;
		}else{	//此时x前半>y前半
			s2 += slen;
			e2 -= slen;
		}
		if( e1-s1 > e2-s2 ){	//当x不再是短序列时 交换xy
			//printf("enter\n");
			int* z = x;
			x = y;  y = z;
			swap(s1,s2); swap(e1,e2);
		}
	}//出口处a只有2个元素

	//printf("out of while:\n");
	//test(x,y,s1,e1,s2,e2);//

	if( e2-s2 == 1 )	//当y也只剩2元素时
		return max(x[s1],y[s2]);
	int m = (s2+e2)/2;
	if( x[s1]<=y[m] && x[e1]>=y[m] ) //x俩元素分居y[m]左右
		return y[m];
	if( x[e1]<=y[m] ){ //x俩元素都在y[m]左侧
		s1++; e2--;	//此时x[s1]必然不是中位数 舍掉
	}//出口时x只剩一个元素
	else if( x[s1]>=y[m] ){	//x俩元素都在y[m]右侧
		e1--; s2++;	//此时x[e1]必然不是中位数
	}//出口时x只剩一个元素

	//printf("last round:\n");
	//test(x,y,s1,e1,s2,e2);//

	int ylen = e2 - s2 + 1;
	m = (s2+e2)/2;
	if( ylen%2==0 && x[s1]<=y[m] ||	//b长度为偶
		ylen%2!=0 && x[s1]>=y[m] )	//b长度为奇
		return y[m];
	else if( ylen%2==0 )	//b长度为偶
		return min(x[s1],y[m+1]);
	else return max(x[s1],y[m-1]);
}

int main()
{
	int i, j, k, m, n;
	//freopen("ZJU_1004.txt","r",stdin);//
	while( scanf("%d",&m)==1 ){
		for( i=1; i<=m; i++ )	//舍弃a[0],b[0]
			scanf("%d",&a[i]);
		scanf("%d",&n);
		for( i=1; i<=n; i++ )
			scanf("%d",&b[i]);

		调试用:
		//n = 100 - m;	//1~100为测试数据 中位数必然是50
		//srand(time(NULL));	//初始化随机数生成器
		//for( i=1,j=1,k=1; i<=m; k++ ){
		//	if( rand()%2==0 || j==n+1 )
		//	{ a[i] = k; i++; }
		//	else if( j<=n )
		//	{ b[j] = k; j++; }
		//}
		//if( j<n )
		//	for( i=j; i<=n; i++,k++ )
		//		b[i] = k;

		if( m < n )
			result = she( a, b, 1,m,1,n);
		else result = she( b, a, 1,n,1,m);

		printf("%d\n",result);

	}
	//while(1);//
	return 0;
}


九度OJ 题目1005:Graduate Admission
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:1254  解决:328
题目描述:
        It is said that in 2011, there are about 100 graduate schools ready to proceed over 40,000 applications in Zhejiang Province. It would help a lot if you could write a program to automate the admission procedure.
        Each applicant will have to provide two grades: the national entrance exam grade GE, and the interview grade GI. The final grade of an applicant is (GE + GI) / 2. The admission rules are:
        ? The applicants are ranked according to their final grades, and will be admitted one by one from the top of the rank list.
        ? If there is a tied final grade, the applicants will be ranked according to their national entrance exam grade GE. If still tied, their ranks must be the same.
        ? Each applicant may have K choices and the admission will be done according to his/her choices: if according to the rank list, it is one's turn to be admitted; and if the quota of one's most preferred shcool is not exceeded, then one will be admitted to this school, or one's other choices will be considered one by one in order. If one gets rejected by all of preferred schools, then this unfortunate applicant will be rejected.
        ? If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.
输入:
        Each input file may contain more than one test case.
        Each case starts with a line containing three positive integers: N (≤40,000), the total number of applicants; M (≤100), the total number of graduate schools; and K (≤5), the number of choices an applicant may have.
        In the next line, separated by a space, there are M positive integers. The i-th integer is the quota of the i-th graduate school respectively.
        Then N lines follow, each contains 2+K integers separated by a space. The first 2 integers are the applicant's GE and GI, respectively. The next K integers represent the preferred schools. For the sake of simplicity, we assume that the schools are numbered from 0 to M-1, and the applicants are numbered from 0 to N-1.
输出:
        For each test case you should output the admission results for all the graduate schools. The results of each school must occupy a line, which contains the applicants' numbers that school admits. The numbers must be in increasing order and be separated by a space. There must be no extra space at the end of each line. If no applicant is admitted by a school, you must output an empty line correspondingly.
样例输入:
    11 6 3
    2 1 2 2 2 3
    100 100 0 1 2
    60 60 2 3 5
    100 90 0 3 4
    90 100 1 2 0
    90 90 5 1 3
    80 90 1 0 2
    80 80 0 1 2
    80 80 0 1 2
    80 70 1 3 2
    70 80 1 2 3
    100 100 0 2 4
样例输出:
    0 10
    3
    5 6 7
    2 8
    1 4
题目并不难 不过要求思路清晰 类似r[index][1]、admit[index][t[index]]这种结构 要很清楚其表述的是啥意思 才能快速AC

//浙大2010:题目1005:Graduate Admission 
//input:
//1st line: 学生数N<=4w 学校数M<=100 志愿数K<=5
//2nd line: M个学校的录取人数
//N lines: N个学生的GE GI K个志愿
#include <fstream>
#include <memory.h>
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
struct STUDENT{
	int id;	//id=原始序号
	int ge, gi, c[5];	//c[]=5个志愿
	//int admit;	//表是否被录取
};
STUDENT a[40000];
int s[300], t[300];	//s[]=录取计划人数 t[]=当前实际录取人数
int r[300][2];	//各学校分数线
int admit[100][40000];

bool cmp( STUDENT x, STUDENT y ){
	int xT = x.ge+x.gi;
	int yT = y.ge+y.gi;
	if( xT == yT )
		return x.ge > y.ge;
	else return xT > yT;
}

int main()
{
	int i, j, k, m, n;
	int index;
	freopen("ZJU_1005.txt","r",stdin);//
	while( scanf("%d%d%d",&n,&m,&k)==3 ){
		for( i=0; i<m; i++ )
			scanf( "%d", &s[i] );
		for( i=0; i<n; i++ ){
			scanf( "%d%d", &a[i].ge, &a[i].gi );
			for( j=0; j<k; j++ )	//k个志愿
				scanf( "%d", &a[i].c[j] );
			a[i].id = i;
		}
		//for( i=0; i<n; i++ )//
		//	printf( "%d %d\n", a[i].ge, a[i].gi );//
		sort( a, a+n, cmp );
		memset(t,0,sizeof(t));

		for( i=0; i<n; i++ ){
			for( j=0; j<k; j++ ){
				index = a[i].c[j];	//index=志愿学校号
				if( t[index] < s[index] ){
					admit[index][t[index]] = a[i].id;
					t[index]++;	//t[]初始=0 录取x个学生时为x
					if( t[index] == s[index] ){	//记录最低录取分数线
						r[index][0] = a[i].ge;
						r[index][1] = a[i].gi;
					}
					break;
				}
				else if( a[i].ge==r[index][0] && a[i].gi==r[index][1] ){
					admit[index][t[index]] = a[i].id;
					t[index]++;
					break;
				}
			}
		}

		for( i=0; i<m; i++ )
			if( t[i]==0 ) printf("\n");
			else{
				sort(admit[i],admit[i]+t[i]);
				for( j=0; j<t[i]-1; j++ )
					printf( "%d ", admit[i][j] );
				printf( "%d\n", admit[i][t[i]-1] );
			}

	}
	while(1);//
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值