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

九度OJ 题目1003:A+B
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:2457  解决:976
题目描述:
    给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。
    现在请计算A+B的结果,并以正常形式输出。
输入:
    输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。
输出:
    请计算A+B的结果,并以正常形式输出,每组数据占一行。
样例输入:
    -234,567,890 123,456,789
    1,234 2,345,678
样例输出:
    -111111101
    2346912

非长整数计算 只需字符转数字处理后再运算即可

//浙大2010:题目1003:A+B 
//input:由两个整数A和B组成(-10^9 < A,B < 10^9)。
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

int process( string s ){
	int a[9], i, j, start, sign;
	if( s[0]==45 ) { sign = -1; start = 1; }
	else { sign = 1; start = 0; }
	int len = s.length();
	for( i=start,j=0; i<len; i++ )
		if( s[i]!=',' ) a[j++] = s[i] - 48;

	int at = a[0];
	for( i=1; i<j; i++ )
		at = at*10 + a[i];
	
	return at*sign;

} 

int main()
{
	int i, j, k, m, n;
	string as, bs;
	int result;
	//ifstream cin("ZJU_1003.txt");//
	while( cin >> as >> bs ){
		result  = process( as ) + process( bs );
		cout << result << endl;
	}
	//system("pause");
	return 0;
}


九度OJ题目1006:ZOJ问题
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:2532  解决:650
题目描述:
    对给定的字符串(只包含'z','o','j'三种字符),判断他是否能AC。
    是否AC的规则如下:
    1. zoj能AC;
    2. 若字符串形式为xzojx,则也能AC,其中x可以是N个'o' 或者为空;
    3. 若azbjc 能AC,则azbojac也能AC,其中a,b,c为N个'o'或者为空;
输入:
    输入包含多组测试用例,每行有一个只包含'z','o','j'三种字符的字符串,字符串长度小于等于1000。
输出:
    对于给定的字符串,如果能AC则请输出字符串“Accepted”,否则请输出“Wrong Answer”。
样例输入:
    zoj
    ozojo
    ozoojoo
    oozoojoooo
    zooj
    ozojo
    oooozojo
    zojoooo
样例输出:
    Accepted
    Accepted
    Accepted
    Accepted
    Accepted
    Accepted
    Wrong Answer
    Wrong Answer

虽然第一眼看去像是DP题 但是有规律可循的 首先z j各一个 其次被z和j分成3段的o的个数满足(i,j,i*j) i>=0 j>=1的关系

//浙大2010:题目1006:ZOJ问题
//AC条件:(i,1,i)->(i,2,2i)->(i,3,3i)->...
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

int main()
{
	int i, z, oo, j, other;
	string s;
	//ifstream cin("ZJU_1006.txt");//
	while( cin >> s ){
		int len = s.length();
		int zflag, jflag;
		z = oo = j = other = 0;
		for( i=0; i<len; i++ ){
			if( s[i]=='z' ){
				z++;
				zflag = i;
			}
			else if( s[i]=='o' )
				oo++;
			else if( s[i]=='j' ){
				j++;
				jflag = i;
			}
			else other++;
		}
		if( other!=0 || z!=1 || j!=1 ){
			cout << "Wrong Answer\n";
			continue;
		}
		int o[3];
		o[0] = zflag;
		o[1] = jflag-zflag-1;
		o[2] = oo - o[0] - o[1];
		if( o[1] == 0 || o[2]!=o[0]*o[1] )
			cout << "Wrong Answer\n";
		else cout << "Accepted\n";
	}
	//system("pause");
	return 0;
}


九度OJ题目1007:奥运排序问题
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:1773  解决:311
题目描述:
    按要求,给国家进行排名。
输入:
    有多组数据。
    第一行给出国家数N,要求排名的国家数M,国家号从0到N-1。
    第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万)。
    接下来一行给出M个国家号。
输出:
    排序有4种方式: 金牌总数 奖牌总数 金牌人口比例 奖牌人口比例
    对每个国家给出最佳排名排名方式 和 最终排名
    格式为: 排名:排名方式
    如果有相同的最终排名,则输出排名方式最小的那种排名,对于排名方式,金牌总数 < 奖牌总数 < 金牌人口比例 < 奖牌人口比例
    如果有并列排名的情况,即如果出现金牌总数为 100,90,90,80.则排名为1,2,2,4.
    每组数据后加一个空行。
样例输入:
    4 4
    4 8 1
    6 6 2
    4 8 2
    2 12 4
    0 1 2 3
    4 2
    8 10 1
    8 11 2
    8 12 3
    8 13 4
    0 3
样例输出:
    1:3
    1:1
    2:1
    1:2
    1:1
    1:1

这道题比较综合 难度其实不算大 但一些细节需要注意

首先 要排序的国家是被选择的 这很好理解 因为可能是要亚洲区的排名 此时当然不能输出亚洲每个国家在世界整体范围的排名而应是本洲内的排名 这时就需要把选定的那些国家拼在一起 比如4个国家c[0]~c[3] 要排序0和3 就要把c[3]的数据挪到c[1]上 因为STL的sort或qsort都是要求被排序内容下标连续的

对于挪移这个问题 一种处理的方式是先记录好所有要排序的国家号 再对这个记录进行升序排序 然后一个个挪移 不过这种方法就需要维护两个记录 因为排序会抹杀掉原来输入的记录 而该记录是最后输出结果所需要的[此时认定题目中输入的国家号可能乱序且输出时要按输入的顺序进行] 另一种方法就是编程珠玑第一栏就给出的bitmap方法了 位图排序方法有一定局限性 不过此问题刚好适合 不仅速度更快 也没有上述的缺点

其次 gdp和mdp可以在拼到一起之后再算 这样只需算m次 而在输入n个国家时就算则要算n次

另外 要注意处理平局情况的排名 一个简单策略就是去比对排名小一位的国家的成绩是否和自己相等 若相等则把人家的排名copy到自己身上即可

最后 用for循环4次+switch可以把程序写的相对简洁易读点

test函数是调试用的输出 其他一些被注释掉的调试语句也保留了

//浙大2010:题目1007:奥运排序问题 
//input:第一行给出国家数N,要求排名的国家数M,国家号从0到N-1。
//第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万)。
//接下来一行给出M个国家号。
//output:对每个国家给出最佳排名排名方式 和 最终排名

#include <fstream>
#include <memory.h>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
struct COUNTRY{
	int gold, medal, population;
	int index;	//保留原始序号
	double gdp, mdp;	//gdp=gold/population
};
#define N 300
COUNTRY c[N];
int mc[N], best[N], bestway[N];
int s[N][4];	//s=sort 记录4种排序的序号情况
bool selected[N];

bool cmp1( const COUNTRY &x, const COUNTRY &y ){
	return x.gold > y.gold;
}
bool cmp2( const COUNTRY &x, const COUNTRY &y ){
	return x.medal > y.medal;
}
bool cmp3( const COUNTRY &x, const COUNTRY &y ){
	return x.gdp > y.gdp;
}
bool cmp4( const COUNTRY &x, const COUNTRY &y ){
	return x.mdp > y.mdp;
}

void chooseBest( int &m ){
	int i, j;
	//for( j=0; j<4; j++ ){
	//	for( i=0; i<m; i++ )
	//		cout<<"s[mc["<<i<<"]]["<<j<<"]="<<s[mc[i]][j]<<" ";
	//	cout << endl;
	//}

	for( i=0; i<m; i++ ){
		best[mc[i]] = min( min(s[mc[i]][0],s[mc[i]][1]),
         min(s[mc[i]][2],s[mc[i]][3]) );
		for( j=0; j<4; j++ )
			if( s[mc[i]][j] == best[mc[i]] ){ //保证了相同最佳排名时 取排名方式号最小的
				bestway[mc[i]] = j + 1;
				break;
			}
	}

	for( i=0; i<m; i++ )
		cout << best[mc[i]] << ":" << bestway[mc[i]] << endl;
	cout << endl;//
}

void test( int m ){
	for(int i=0; i<m; i++ )
		cout<<c[i].index<<":"<<"  "<<c[i].gold<<"  "        
        <<c[i].medal<<"  "<<c[i].gdp<<"  "<<c[i].mdp<<endl;
}

int main()
{
	int i, j, k, m, n;
	ifstream cin("ZJU_1007.txt");//
	while( cin >> n >> m ){	//n个国家 其中m个要排序
		memset(selected, 0, sizeof(selected));
		for( i=0; i<n; i++ ){
			cin >> c[i].gold >> c[i].medal >> c[i].population;
			c[i].index = i;
		}
		for( i=0; i<m; i++ ){
			cin >> mc[i];
			selected[mc[i]] = 1;
		}

		if( m!=n )
			for( i=0,j=0; i<n; i++ )	//剃掉不需排队的国家
				if( selected[i] ){	//需要排队且和当前欲写入下标不同时才写入
					if( i==j )
						{ j++; continue; }
					//cout<<i<<" selected\n";//
					c[j] = c[i];//
					j++;
				}
		
		for( i=0; i<m; i++ ){	//并不在输入时就算好 因为不需排序的国家不必算
			c[i].gdp = (double)c[i].gold/c[i].population;
			c[i].mdp = (double)c[i].medal/c[i].population;
		}

		//cout << "original:\n";  test(m);  cout<<endl;//

		for( j=0; j<4; j++ ){
			switch(j){
				case 0: sort( c, c+m, cmp1 ); break;
				case 1: sort( c, c+m, cmp2 ); break;
				case 2: sort( c, c+m, cmp3 ); break;
				case 3: sort( c, c+m, cmp4 ); break;
			}

			//cout << "mode["<<j<<"]:\n";  test(m);  cout<<endl;//

			s[c[0].index][j] = 1;
			for( i=1; i<m; i++ ){
				s[c[i].index][j] = i+1;	//s[2][0]表示2号国家的第一种排名
				switch(j)
				{
					case 0: if( c[i].gold==c[i-1].gold )
								s[c[i].index][j] = s[c[i-1].index][j]; break;
					case 1: if( c[i].medal==c[i-1].medal )
								s[c[i].index][j] = s[c[i-1].index][j]; break;
					case 2: if( c[i].gdp==c[i-1].gdp )
								s[c[i].index][j] = s[c[i-1].index][j]; break;
					case 3: if( c[i].mdp==c[i-1].mdp )
								s[c[i].index][j] = s[c[i-1].index][j]; break;
				}
			}
		}//四重排序for

		chooseBest(m);

	}
	system("pause");
	return 0;
}


九度OJ题目1008:最短路径问题
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:1474  解决:383
题目描述:
    给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入:
    输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
    (1<n<=1000, 0<m<100000, s != t)
输出:
    输出 一行有两个数, 最短距离及其花费。
样例输入:
    3 2
    1 2 5 6
    2 3 4 5
    1 3
    0 0
样例输出:
    9 11
还没做 图的问题基本没碰过啊有木有

九度OJ题目1009:二叉搜索树
时间限制:1 秒  内存限制:32 兆  特殊判题:否  提交:876  解决:402
题目描述:
    判断两序列是否为同一二叉搜索树序列
输入:
    开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束。
    接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树。
    接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树。
输出:
    如果序列相同则输出YES,否则输出NO
样例输入:
    2
    567432
    543267
    576342
    0
样例输出:
    YES
    NO

这题WA卡了我半周 百思不得其解 郁闷之极 后来发现 人家要求输出YES我输出的是yes 眼泪都下来了有木有 T_T

多说一句 二叉排序树的中序遍历是一样的 都是所有元素的升序排列 所有判等只需校验先序遍历是否相等即可 因为前序+中序确定一棵二叉树嘛

//浙大2010:题目1009:二叉搜索树
//判断两序列是否为同一二叉搜索树序列
//input:开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束。
//接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字
//接下去的n行有n个序列,请判断它和第一个序列是否能组成同一颗二叉搜索树。

#include <fstream>
#include <string>
#include <iostream>
using namespace std;
struct BiTree{
	char c;
	BiTree* l;
	BiTree* r;
};
string inOrder, preOrder;

void insertNode( BiTree *Root, char ch ){
	BiTree *t = new BiTree();	//新生成节点
	t->c = ch;
	t->l = t->r = NULL;
	BiTree *p = Root;	//查找指针
	while( true ){
		if( ch < p->c ){
			if( p->l!=NULL ) p = p->l;
			else { p->l = t; break;	}
		}
		else if( p->r!=NULL ) p = p->r;
		else { p->r = t; break;	}
	}
}

BiTree* buildTree( string s ){
	BiTree *Root = new BiTree();  //t=tree
	Root->c = s[0];
	Root->l = Root->r = NULL;

	int len = s.length();
	for( int i=1; i<len; i++ )
		insertNode( Root, s[i] );
	return Root;
}

void preTraverse( BiTree* t ){
	if( t != NULL ){
		preOrder += t->c;
		if( t->l != NULL)
			preTraverse(t->l);
		if( t->r != NULL)
			preTraverse(t->r);
	}
};

int main()
{
	int i, j, k, m, n, len;
	string a, b, Ain, Apre, Bin, Bpre;
	ifstream cin("ZJU_1009.txt");//
	while( cin >> n && n!=0 ){
		cin >> a;
		preOrder = "";
		preTraverse( buildTree(a) );
		Apre = preOrder;
		//cout << "Apre=" << Apre << endl;

		for( i=0; i<n; i++ ){
			cin >> b;
			preOrder = "";
			preTraverse( buildTree(b) );
			Bpre = preOrder;
			//cout << "Bpre=" << Bpre << endl;

			if( Apre == Bpre )
				cout << "YES\n";
			else 
				cout << "NO\n";
		}
	}
	system("pause");
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值