北大郭炜慕课程序设计与算法(一)C++的OpenJudge题目答案

北大郭炜慕课程序设计与算法(一)C++的OpenJudge题目答案

学习心得

2022下半年学习了郭炜老师的C++课程,郭老师的教学深入浅出,尤为可贵的是能讲清楚知识的前后联系和知识的架构,此外本课程的特点是排除了C++面向对象的特性,也即不讲授所谓类、对象等概念,对初学者友好,很建议新手自学本课,课程链接如下:北大郭炜慕课程序设计与算法(一)
OpenJudge题目的链接是:OpenJudge题目。下面会展示我所做的题目的答案,以及一些针对题目和概念的心得
做题时参考了虾米不打烊的文章,链接如下:虾米不打烊的文章

题目答案

001 输出第二个整数

#include<iostream>
#include<cstdio>  
using namespace std;
int main(){
	int a;int b;int c;
	scanf("%d%d%d",&a,&b,&c); 
	printf("%d",b);
	return 0;
}

002 字符菱形

#include<iostream>
#include<cstdio> 
using namespace std;
int main(){
	char a;
	scanf("%c",&a);  
	printf("  %c  \n",a);
	printf(" %c%c%c \n",a,a,a);
	printf("%c%c%c%c%c\n",a,a,a,a,a);
	printf(" %c%c%c \n",a,a,a);
	printf("  %c  \n",a);
	return 0;
}

003 打印ASCII码

cin、cout输出会比上面所用的scanf和printf更方便,速度也更快,并且可以操作符重载。

#include<iostream>
#include<cstring> 
using namespace std;
int main(){
	char a;int b;
	cin>>a;
	b=a;
	cout<<b<<endl;
	return 0;
}

004 打印字符

#include<iostream>
#include<cstring> 
using namespace std;
int main(){
	char a;int b;
	cin>>b; 
	a=b;
	cout<<a<<endl;
	return 0;
}

005 整型数据类型存储空间大小

#include<iostream>
#include<cstring> 
using namespace std;
int main(){
	int a;short b;
	cout<<sizeof(a)<<" "<<sizeof(b);
	return 0;
}

006 浮点型数据类型存储空间大小

sizeof是重要的,后面对于复杂的数据类型我们会常用到。

#include<iostream>
#include<cstring> 
using namespace std;
int main(){
	float a;double b;
	cout<<sizeof(a)<<" "<<sizeof(b);
	return 0;
}

007 对齐输出

用cout格式化输出有很多特性,除此以外还有ostream 类的成员方法。

#include<iostream>
//#include<cstdio> //使用scanf和printf需要加入cstdio库
#include<cstring> 
#include <iomanip>
using namespace std;
int main() {
	int a; int b; int c;
	cin >> a >> b >> c;
	/*
	cout.width(8);
	cout.setf(ios::right);
	cout << a <<" " << b<<" " << c;
	*/
	cout << setw(8) << a << ' ' << setw(8) << b << ' ' << setw(8) << c << endl;
	return 0;
}

008 输出保留12位小数的浮点数

#include<iostream>
//#include<cstdio> //使用scanf和printf需要加入cstdio库
#include<cstring> 
using namespace std;
int main() {
	double a; 
	cin >> a;
	//精度是指小数点位数
	cout.setf(ios::showpoint);
	cout.setf(ios::fixed);
	cout.precision(12);
	cout << a ;
	return 0;
}

009 空格分隔输出

#include<iostream>
//#include<cstdio> //使用scanf和printf需要加入cstdio库
#include<cstring> 
#include <iomanip>
using namespace std; 
int main() {
	char a; int b; float c; double d;
	cin >> a >> b >> c>>d;
	cout.setf(ios::showpoint);
	cout.setf(ios::fixed);
	cout.precision(6);
	cout << a << " " << b << " " <<c<<" "<<d;
	return 0;
}

010 计算球的体积

注意在计算时变量的数据类型转换。

#include<iostream>
//#include<cstdio> //使用scanf和printf需要加入cstdio库
#include<cstring> 
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
	double V; double r;
#define pi 3.14
	cin >> r;
	V = 4.0 / 3.0 * pi * pow(r, 3);	
	cout.setf(ios::showpoint);
	cout.setf(ios::fixed);
	cout.precision(2);
	cout<<V;
	return 0;
}

011 大象喝水

多种舍入规则对应不同的函数。

#include<iostream>
#include<cstring> 
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
	int h; int r;
	double V;
	int n;
#define pi 3.14159
	cin >> h>>r;
	V = pi *h* pow(r, 2)/1000;
	n = ceil(20/V);
	cout << n;
	return 0;
}

012 奇偶数判断

#include<iostream>
#include<cstring> 
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
	int n;
	cin >> n;
	if (n % 2)
	{
		cout << "odd";
	}
	else {
		cout << "even";
	}
	return 0;
}

013 求一元二次方程的根

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <math.h>
using namespace std;

int main() {
	double a; double b; double c;
	double x1; double x2;
	double real; double imaginary;
	
	cin >> a >> b >> c;

	x1 = (-b + sqrt(b * b - 4 * a * c)) / (2 * a);
	x2 = (-b - sqrt(b * b - 4 * a * c)) / (2 * a);
	if (b == 0)real = 0;
	else 
		real = -1 * (b / (2 * a));
		
	imaginary = sqrt(4 * a * c - b * b) / (2 * a);
	
	cout.setf(ios::showpoint);
	cout.setf(ios::fixed);
	cout.precision(5);

	if (pow(b,2)==4*a*c){
		cout << "x1=x2=" << x1;
	}
	else if (pow(b, 2) > 4 * a * c){
		cout << "x1=" << x1 << ";" << "x2=" << x2;
	} 
	else if(pow(b, 2) < 4 * a * c){
		cout << "x1=" << real << "+"<<imaginary<<"i" << ";" << "x2=" << real << "-" << imaginary <<"i";
	}
	return 0;
}

014 点和正方形的关系

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <math.h>
using namespace std;

int main() {
	int x; int y;
	cin >> x >> y;

	if (abs(x) <= 1 && abs(y) <= 1)
		cout << "yes";
	else
		cout << "no";

	return 0;
}

015 苹果和虫子2

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
	int n; int x; int y; int r;
	cin >>n>> x >> y;

	r = n - ceil(y * 0.1 / (x * 0.1));//一种转换方法
	if (r <= 0)
		cout << 0;
	else
		cout << r;

	return 0;
}

016 简单计算器

使用ASCii码。

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
	int a; int b; char o;
	cin >> a >> b >> o;

	if (o != 42 && o != 43 && o != 45 && o != 47)
		cout << "Invalid operator!";
	else
		switch (o) {
		case 42:
				cout << a * b;
				break;
			case 43:
				cout << a + b;
				break;
			case 45:
				cout << a - b;
				break;
			case 47:
				if (b == 0) {
					cout << "Divided by zero!";
					break;
				}
				else {
					cout << a / b;
					break;
				}
		}
	return 0;
}

017 求整数的和与均值

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
	int n; int x; int sum;
	sum = 0;
	cin >> n;

	for (int i = 0; i <= n - 1; ++i) {
		cin >> x;
		sum += x;
	}

	cout.setf(ios::showpoint);
	cout.setf(ios::fixed);
	cout.precision(5);

	cout << sum <<" "<< sum * 0.1 / (n * 0.1);

	return 0;
}

018 整数序列的元素最大跨度值

找最大最小值。

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
	int n; int x; int max; int min;
	max = 0;
	min = 1000;
	cin >> n;

	for (int i = 0; i <= n - 1; ++i) {
		cin >> x;
		if (x > max)
			max = x;
		if (x < min)
			min = x;
	}

	cout << max-min;

	return 0;
}

019 奥运奖牌计数

#include <iostream>
#include <cstring> 
#include <iomanip>
#include <cmath>
using namespace std;

int main() {
	int n; int gold; int sliver; int copper;
	int sg; int ss; int sc;
	sg = 0;
	ss = 0;
	sc = 0;

	cin >> n;

	for (int i = 0; i <= n - 1; ++i) {
		cin >> gold>>sliver>>copper;
		sg += gold;
		ss += sliver;
		sc += copper;
	}

	cout << sg<<" "<<ss<<" "<<sc<<" "<< sg + ss + sc;

	return 0;
}

020 乘方计算

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int a, n;
	int result = 1;

	cin >> a >> n;
	for (int i = 1; i <= n; ++i)
		result *= a;

	cout << result;

	return 0;
}

021 鸡尾酒疗法

使用数组。

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
    int n; int x, y;
	double therapy[20] = { 0 }, cocktail = 0; int flag[20] = { 0 };
	int count = 0;

	cin >> n;

	for (int i = 0; i <= n - 1; ++i){
		cin >> x >> y;
		++count;//if cin.get....
		
		if (count == 1) {
			cocktail = double(y) / double(x);//y * 0.1 / (x * 0.1)
		}
		else {
			therapy[i] = double(y) / double(x);
		}

			if (therapy[i] - cocktail > 0.05)
				flag[i] = 1;
			else if ( cocktail - therapy[i] > 0.05)
				flag[i] = 2;
			else
				flag[i] = 3;
	}

	for (int i = 1; i <= n - 1; ++i) {

		if(flag[i] == 1)
			cout << "better"<<endl;
		else if (flag[i] == 2)
			cout << "worse" << endl;
		else if(flag[i] == 3)
			cout << "same" << endl;
	}

	return 0;
}

022 角谷猜想

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;

int main() {
	long n;
	cin >> n;

	while (n != 1) {
		if (n % 2 != 0) {
			n = n * 3 + 1;
			cout << n/3 << "*3+1=" << n<<endl;
		}
		else {
			n = n / 2;
			cout << n*2<< "/2=" << n<<endl;
		}
	}
	cout << "End";
	return 0;
}

023 正常血压

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int n; int x, y;
	int count = 0;
	int maxcount = 0;

	cin >> n;

	for (int i = 0; i <= n - 1; ++i) {
		cin >> x >> y;
		
		if (x >= 90 && x <= 140 && y >= 60 && y <= 90) {
			++count;
			if(maxcount<=count)
			maxcount = count;
		}
		else
			count = 0;
	}
	cout << maxcount;
	
	return 0;
}

024 数字反转

做题时有一些思考,写在注释中。

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
//必须得知道n的范围
	//int n,a,b,c;
	//cin >> n;

	//a = n % 10;
	//b = n / 10 % 10;
	//c = n / 100;

//其实还是得知道a的位数
	int a, b=0;
	cin >> a;
	while (a) {
		b = b * 10 + a % 10;
		a = a / 10;
	}
	cout << b;

	return 0;
}

025 求特殊自然数

# include<iostream>
using namespace std;
//这个数一定在81-342范围里
int main()
{
    for (int i = 81; i < 343; i++) {
        //转为7进制
        int j = i;
        int yushu11 = j % 7;
        j = j / 7;
        int yushu12 = j % 7;
        j = j / 7;
        int yushu13 = j % 7;
        j = j / 7;
        //转为9进制
        j = i;
        int yushu21 = j % 9;
        j = j / 9;
        int yushu22 = j % 9;
        j = j / 9;
        int yushu23 = j % 9;
        j = j / 9;
        //看是不是相反的关系
        if (yushu11 == yushu23 && yushu12 == yushu22 && yushu13 == yushu21) {
            cout << i<<endl;
            cout << yushu13 << yushu12 << yushu11<<endl;
            cout << yushu23 << yushu22 << yushu21<<endl;
        }
        //是就输出,再找找后面的
    }
    return 0;
}

026 雇佣兵

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int m, n, x,count=0;
	cin >> m >> n >> x;

	//按照   开始每个战斗期时   有无能量元素
	while (x*n >= m) {
		++count;
		x -= ceil(double(m) / double(n));
		if (m >= n)
			n += floor(m / n);
	}

	cout << n;

	return 0;
}

027 数字统计

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int l, r; int x ;
	int count = 0;
	cin >> l >> r;

	for (int i = l; i <= r; ++i) {
		x = 1;

		while (1) {
			if ((i / x) % 10 == 2) {
				++count;
			}
				x *= 10;
			
			if (i / x == 0)
				break;
			}
		}
	cout << count;

	return 0;

}

028 与指定数字相同的数的个数

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;

int main() {
	int n, m,count=0;
	cin >> n;
	int* a = new int[n];

	for (int i = 0; i <= n - 1; ++i) {
		cin >> a[i];
	}

	cin >> m;

	for (int i = 0; i <= n - 1; ++i) {
		if (a[i] == m)
			++count;
	}
	
	cout << count;
	
	return 0;
}

029 陶陶摘苹果

#include<iostream>
using namespace std;
int main() {
	int a[10], b, count = 0;
	for (int i = 0; i <= 9; ++i)
		cin >> a[i];

	cin >> b;
	for (int i = 0; i <= 9; ++i)
		if (a[i] - b - 30 <= 0)
			++count;
	cout << count;

	return 0;

030 年龄与疾病

#include <iostream>
#include <iomanip>

using namespace std;
int main() {
	int n; int aa = 0, bb = 0, cc = 0, dd = 0;
	int age[100];

	cin >> n;
	for (int i = 0; i <= n - 1; ++i)
		cin >> age[i];

	for (int i = 0; i <= n - 1; ++i) {
		
		if (age[i] > 0 && age[i] <= 18)
			++aa;
		else if(age[i] >= 19 && age[i] <= 35)
			++bb;
		else if (age[i] >= 35 && age[i] <= 60)
			++cc;
		else  
			++dd;
	}

	cout.setf(ios::fixed);
	cout.setf(ios::showpoint);
	cout.precision(2);

	cout << double(100 * aa) / n << "%" << endl;
	cout << double(100 * bb) / n << "%" << endl;
	cout << double(100 * cc) / n << "%" << endl;
	cout << double(100 * dd) / n << "%" << endl;

	return 0;

}

031 校门外的树

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;

int main() {
	int l, m; int low, up; int count = 0;
	int a[10001] = {0};

	cin >> l >> m;
	for (int i = 0; i <= m - 1; ++i) {
		cin >> low >> up;
		
		for (int j = low; j <= up; ++j) {
			a[j] = 1;//直接计数也可,但可能会遇到重复的区域
		}
	}

	for (int k = 0; k <= 10000; ++k)
		count += a[k];

	cout << l+1-count;
	return 0;

}

032 计算鞍点

用到了memset对数组初始化。

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int rmax[5], cmin[5] = { 1000000,1000000 ,1000000 ,1000000 ,1000000 };
	memset(rmax, 0, sizeof(rmax));
	int t = 4;
	int a[5][5];

	for (int i = 0; i <= 4; ++i) {
		for (int j = 0; j <= 4; ++j) {
			cin >> a[i][j];
		}
	}

	for (int i = 0; i <= 4; ++i) {
		for (int j = 0; j <= 4; ++j) {
			if (a[i][j] > rmax[i])
				rmax[i] = a[i][j];
			if (a[i][j] < cmin[j])
				cmin[j] = a[i][j];
		}
	}

	for (int i = 0; i <= 4; ++i) {
		for (int j = 0; j <= 4; ++j) {
			if (a[i][j] == rmax[i] && a[i][j] == cmin[j]) {
				cout << i+1 << " " << j+1 << " " << a[i][j];
				--t;
			}
		}
	}

	if (t == 4)
		cout << "not found";
	return 0;
}

033 图像模糊处理

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int n, m;
	int a[100][100]; int b[100][100];//一定要新建一个矩阵,否则计算过程中就会迭代结果
	cin >> n >> m;

	for (int i = 0; i <= n-1; ++i) {
		for (int j = 0; j <= m-1; ++j) {
			cin >> a[i][j];
			b[i][j] = a[i][j];
		}
	}

	for (int i = 1; i <= n - 2; ++i) {
		for (int j = 1; j <= m - 2; ++j) {
			b[i][j]= round((double(a[i][j])+double(a[i-1][j])+ double(a[i+1][j])+ double(a[i][j-1])+ double(a[i][j+1]))*0.20);
		}
	}

	for (int i = 0; i <= n - 1; ++i) {
		for (int j = 0; j <= m - 1; ++j) {
			cout<<b[i][j]<<" ";
			while (j == m - 1) {
				cout << endl;
				break;
			}
		}
	}

	return 0;
}

034 矩阵转置

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	int n, m;
	int a[100][100]; int b[100][100];
	cin >> n >> m;

	for (int i = 0; i <= n - 1; ++i) {
		for (int j = 0; j <= m - 1; ++j) {
			cin >> a[i][j];
			b[j][i] = a[i][j];
		}
	}
	
	//考虑向量的情况
	if (n == 1) {//别忘了是==
		for (int i = 0; i <= m - 1; ++i) {
				cout << b[i][0] << endl;
		}
	}

	else if (m == 1) {
		for (int i = 0; i <= n - 1; ++i) {
			cout << b[0][i] << " ";
		}
	}

	//矩阵情况
	else {
		for (int i = 0; i <= m - 1; ++i) {
			for (int j = 0; j <= n - 1; ++j) {
				cout << b[i][j] << " ";
				while (j == n - 1) {
					cout << endl;
					break;
				}
			}
		}
	}

	return 0;
}

035 Pell数列

#include <bits/stdc++.h>
using namespace std;
int b[1000001]; //提前计算出数列每一项的值 
int main() {
	int n;
	cin>>n;
	int a[n];
	for(int i=0; i<n; i++) {
		cin>>a[i];
	}
	b[0]=1;
	b[1]=2;
	//计算数列 
	for(int i=2; i<=1000000; i++) {
		b[i]=(2*b[i-1]+b[i-2])%32767;//利用高精度思想,每次计算后都取模 
	}
	for(int i=0; i<n; i++) {
		cout<<b[a[i]-1]<<endl;//输出第i位的值,由于数列下标从0开始,要减1 
	}
}

036 求最大公约数问题

调用函数。

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int commonfactor(int a, int b) {
	int cf; int c;
	
	if (a % b != 0) {
		c = a;
		a = b;
		b = c % b;
		return commonfactor(a, b);
	}

	if (a % b == 0)
		return b;
}

int main() {
	int a, b, c;
	cin >> a>> b;

	if (b < a) {
		c = a;
		a = b;
		b = c;
	}

	cout << commonfactor(a, b);
	
	return 0;
}

037 编程填空:第i位替换

#include <iostream>
using namespace std;

int bitManipulation1(int n, int m, int i) {
 return n - (n & (1 << i)) + (m & (1 << i));
}

int main() {
	int n, m, i, t;
	cin >> t;
	while (t--) { 
		cin >> n >> m >> i;
		cout << bitManipulation1(n, m, i) << endl;
	}
	return 0;
}

038 编程填空:第i位取反

#include <iostream>
using namespace std;

int bitManipulation2(int n, int i) {
return (1 << i) ^ n;
}

int main() {
	int t, n, i;
	cin >> t;
	while (t--) {
		cin >> n >> i;
		cout << bitManipulation2(n, i) << endl;
	}
	return 0;
}

039 编程填空:左边i位取反

#include <iostream>
using namespace std;

int bitManipulation3(int n, int i) {
return (-1 << (32-i)) ^ n;
}

int main() {
	int t, n, i;
	cin >> t;
	while (t--) {
		cin >> n >> i;
		cout << bitManipulation3(n, i) << endl;
	}
	return 0;
}

040 统计数字字符个数

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main(){
	char a[10000];
	int n; int count = 0;
	cin.getline(a, sizeof(a));
	
	n = strlen(a);

	for (int i = 0; i <= n - 1; ++i) {
		if (a[i] >= int('0') && a[i] <= int('9'))
			++count;
	}

	cout << count;

	return 0;
}

041 找第一个只出现一次的字符

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
int main() {
	char a[100000]; int n; char the;
	int count = 0;
	cin >> a;
	n = strlen(a);

	for (int i = 0; i <= n - 1; ++i) {
		count = 0;//每次找前置0
		for (int j = 0 ; j <= n - 1; ++j) {
			if (a[i] == a[j]) {
				++count ;//找到就是非0
			}
		}
		//cout << count<<endl;
		if (count==1) {
			cout << a[i];
			return 0;
		}
	}

	cout << "no";

}

042 石头剪子布

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;

int caiquan(string a,string b) {
	if (a == "Rock" && b == "Scissors" || a == "Scissors" && b == "Paper" || a == "Paper" && b == "Rock") {//strcmp
		return 1;
	}
	else if (b == "Rock" && a == "Scissors" || b == "Scissors" && a == "Paper" || b == "Paper" && a == "Rock") {
		return 2;
	}
	else
		return 3;
}
int main() {
	int n; char a[101]; char b[101]; int c[101];
	cin >> n;

	for (int i = 0; i <= n - 1; ++i) {
		cin >> a >> b;
		c[i]= caiquan(a, b);
	}

	for (int i = 0; i <= n - 1; ++i) {
		if (c[i] == 1)
			cout << "Player1" << endl;
		else if (c[i] == 2)
			cout << "Player2" << endl;
		else if (c[i] == 3)
			cout << "Tie" << endl;
	}
	return 0;
}

043 最长最短单词

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
//如果用cin和scanf读入字符串数组,会读入到空格为止 
int main(){
	char a[10000];
	int len_min=300,len_max=0;
	int pos_min,pos_max;
	int count=0;
	cin.getline(a,sizeof(a));
	a[strlen(a)]=' ';//最后一位置为空格,否则遇到一个单词组成的句子将无法判断 
	
	for(int i=0;a[i];++i){
		if(a[i]!=' '&&a[i]!=',')
			++count;
		else if(count!=0){//要加非零的条件,否则每次都自动置零 
			if(count<len_min){
				len_min=count;					
				pos_min=i-count;//记录最短单词起始位置 
			}
			if(count>len_max){
				len_max=count;
				pos_max=i-count;//记录最长单词起始位置 
			}
			count=0; 
		}
	} 

	for(int i=pos_max;i<=pos_max+len_max-1;++i){
		cout<<a[i];
	}
	
	cout<<endl;

	for(int i=pos_min;i<=pos_min+len_min-1;++i){
		cout<<a[i];
	}

	return 0;

}

044 密码翻译

#include <iostream>
#include <cstdio> //使用scanf和printf需要加入cstdio库 
#include <cstring> 
#include <iomanip>//setw
#include <cmath>

using namespace std;
//如果用cin和scanf读入字符串数组,会读入到空格为止 
int main(){
	char a[100];
	int count=0;
	cin.getline(a,sizeof(a));
	
	for(int i=0;a[i];++i){
		if((int(a[i])>=65&&int(a[i])<=89)||(int(a[i])>=97&&int(a[i])<=121))
			a[i]=char(a[i]+1);

		else if(int(a[i])==90||int(a[i])==122)
			a[i]=char(a[i]-25);	
	} 

	for(int i=0;a[i];++i){
		cout<<a[i];
	}

	return 0;

}

045 指针练习:输出Hello

#include <iostream>
using namespace std;
int main() {
	char s[] = "Hello";  
	char * p;
	for(
p=s;*p;p++
)
		cout << * p ;
	return 0;
}

046 指针练习:输出Tesla

#include <iostream>
using namespace std;
void Print(const char * p1, const char * p2) 
{  
	for(
p1;p1<p2;++p1
) 	
		cout << * p1;
}
int main()  
{
	const char * s = "Tesla123";
	Print(s,s+5);
	cout << endl;
	Print(s,s+3);
	cout << endl;
	
	return 0;
}

047 指针练习:ForEach

函数指针。

#include <iostream>
using namespace std;

void ForEach(void * a, int width, int num,
void (*f)(void *p)
)

{
	for(int i = 0;i < num; ++i) 
		f((char*)a+width*i);
}

void PrintSquare(void * p)
{
	int * q = (int*)p;
	int n = *q;
	cout << n * n << ",";
}
void PrintChar(void * p) {
	char * q = (char*)p;
	cout << *q << ",";
}
int main()
{
	int a[5] = {1,2,3,4,5};
	char s[] = "hello!";
	ForEach(a,sizeof(int),5,PrintSquare); 
	cout << endl;
	ForEach(s,sizeof(char),6,PrintChar);
	return 0;
}

048 指针练习:Memcpy之一

#include <iostream>
using namespace std;
void Memcpy(char * src,char * dest,int n)
{
char* pdest=dest;
char* psrc=src;
for(int i=0;i<n;++i){
*(pdest+i)=*(psrc+i);
}

}
int Strlen(char * s)
{	
	int i;
	for( i = 0; s[i]; ++i);
	return i;
}
int main()  
{
	int a;
	char s1[30];
	char s2[30];
	int t;
	cin >> t;
	for(int i = 0;i < t; ++i) {
		cin >> a;
		int b = 99999999;
		Memcpy((char*)&a,(char *) &b,sizeof(int));
		cout << b << endl;
	}
	for(int i = 0;i < t; ++i) {
		cin >> s1;
		Memcpy(s1,s2,Strlen(s1)+1);
		cout << s2 << endl;
	}
	return 0;
}

049 指针练习:double

#include <iostream>
using namespace std;

void Double(int * p, int n)
{
	for(int i = 0;i < n; ++i)
		p[i] *= 2;
}


int main()
{
	int a[3][4] = { { 1,2,3,4},{5,6,7,8},
					{ 9,10,11,12 } };
	
	Double(
a[0]+4,6
);
	for(int i = 0;i < 3; ++i) {
		for(int j = 0; j < 4; ++j)
			cout << a[i][j] << ",";
		cout << endl; 
	}
	
	return 0;
}

050 指针练习:Memcpy之二

#include <iostream>
using namespace std;
void Memcpy( void * src, void * dest, int size)
{
char temp[100];
	for (int i = 0; i < size; i++) {
		temp[i] = *((char*)src + i);
	}
	for (int i = 0; i < size; i++) {
		*((char *)dest+i) = temp[i];
	}

}

void Print(int * p,int size)
{
	for(int i = 0;i < size; ++i)
		cout << p[i] << ",";
	cout << endl;
}

int main()
{
	int a[10];
	int n;
	cin >> n;
	for(int i = 0;i < n; ++i)
		cin >> a[i];
	int b[10] = {0};
	Memcpy(a,b,sizeof(a));
	Print(b,n);
	
	int c[10] = {1,2,3,4,5,6,7,8,9,10};
	Memcpy(c,c+5,5*sizeof(int)); //将c的前一半拷贝到后一半 
	Print(c,10);

	char s[10] = "123456789";
	Memcpy(s+2,s+4,5); //将s[2]开始的5个字符拷贝到s[4]开始的地方 
	cout << s << endl;
	
	char s1[10] = "123456789";
	Memcpy(s1+5,s1+1,4); //将s1[5]开始的4个字符拷贝到s1[1]开始的地方 
	cout << s1 << endl;
	
	
	return 0;
}

051 指针练习:MyMax

#include <iostream>
using namespace std;
char* MyMax(void* a,int width,int num,int(*fun)(void * n1,void * n2)){
char* max=(char*)a;  
  for(int i = 0;i < num; ++i) {
     if(fun(max,(char*)a+width*i)<0){
       max = (char*)(a+width*i);
     }
  }
return max;

}
int Compare1(void * n1,void * n2)
{
	int * p1 = (int * )n1;
	int * p2 = (int * )n2;
	return ((*p1)%10) - ((*p2)%10);
}
int Compare2(void * n1,void * n2)
{
	int * p1 = (int * )n1;
	int * p2 = (int * )n2;
	return *p1 - *p2;
}
#define eps 1e-6
int	Compare3(void * n1,void * n2)
{
	float * p1 = (float * )n1;
	float * p2 = (float * )n2;
	if( * p1 - * p2 > eps)
		return 1;
	else if(* p2 - * p1 > eps)
		return -1;
	else
		return 0; 
}

int main()
{
	int t;
	int a[10];
	float d[10];
	cin >> t;
	while(t--) {
		int n;
		cin >> n;
		for(int i = 0;i < n; ++i)
			cin >> a[i];
		for(int i = 0;i < n; ++i)
			cin >> d[i];
		int * p = (int *) MyMax(a,sizeof(int),n,Compare1);
		cout << * p << endl;
		p = (int *) MyMax(a,sizeof(int),n,Compare2);
		cout << * p << endl;
		float * pd = (float * )MyMax(d,sizeof(float),n,Compare3);
		cout << * pd << endl;
	}
	return 0;
}

052 指针练习:指向指针的指针

#include <iostream>
using namespace std;
int main()
{
	int x,y,z;
	x = 10;
	y = 20;
	z = 30;
	
	int * a[3]  = { &x, &y,&z};
	for(
int **p=a;
p < a + 3; ++p) 
			cout<< * (*p) << endl;
	return 0;
	
}

053 指针练习:SwapMemory

#include <iostream>
using namespace std;
void SwapMemory(void * m1,void * m2, int size)
{
char temp;
char* n1=(char*) m1;
char* n2=(char*) m2;

for(int i = 0;i < size; ++i){
  temp =*(n1+i);
  *(n1+i)=*(n2+i);
  *(n2+i)=temp;
}

}

void PrintIntArray(int * a,int n)
{
	for(int i = 0;i < n; ++i)
		cout << a[i] << ",";
	cout << endl;
}

int main()
{
	int a[5] = {1,2,3,4,5};
	int b[5] = {10,20,30,40,50};
	SwapMemory(a,b,5 * sizeof(int));
	PrintIntArray(a,5);
	PrintIntArray(b,5);
	char s1[] = "12345";
	char s2[] = "abcde";
	SwapMemory(s1,s2,5);
	cout << s1 << endl;
	cout << s2 << endl;
	return 0;
}

054 成绩排序

结构数组。

#include<iostream>
using namespace std;
struct Student{
		string name;
		int grade;
	};
int main() {
	Student s[20];
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> s[i].name >> s[i].grade;
	}

	for (int i = 0; i < n - 1; ++i) {
		int tempmax = i;
		for (int j = i + 1; j < n; ++j) {
			if (s[j].grade > s[tempmax].grade)
				tempmax = j;
			else if (s[j].grade == s[tempmax].grade) {
				if (s[j].name < s[tempmax].name) {
					tempmax = j;
				}
			}
		}

		Student tmp = s[i];
		s[i] = s[tempmax];
		s[tempmax] = tmp;

	}

	for (int i = 0; i < n; ++i) {
		cout << s[i].name << " " << s[i].grade << endl;
	}

}

055 分数线划定

可以采用其他排序方法。

#include<iostream>
using namespace std;
struct Volunteer{
		string number;
		int grade;
	};
int main() {
	
	
	Volunteer c[5000];
	int n,m,p;
	cin >> n >> m;
	p = (int)(m*1.5);
	
	for (int i = 0; i < n; ++i) {
		cin >> c[i].number >> c[i].grade;
	}

	for (int i = 0; i < n - 1; ++i) {
		int tempmax = i;
		for (int j = i + 1; j < n; ++j) {
			if (c[j].grade > c[tempmax].grade)
				tempmax = j;
			else if (c[j].grade == c[tempmax].grade) {
				if (c[j].number < c[tempmax].number) {
					tempmax = j;
				}
			}
		}

		Volunteer tmp = c[i];
		c[i] = c[tempmax];
		c[tempmax] = tmp;

	}

	for(int i = p; i < n; ++i){
		if(c[i].grade == c[p-1].grade)
			++p;
	}

	cout << c[p-1].grade << " " << p << endl;

	for (int i = 0; i < p; ++i) {
		cout << c[i].number << " " << c[i].grade << endl;
	}

}

056 病人排队

#include<iostream>
using namespace std;
struct Patient{
		string id;
		int age;
		int index;
	};
int main() {
	Patient c[100];
	int n;
	cin >> n;	
	for (int i = 0; i < n; ++i) {
		cin >> c[i].id >> c[i].age;
		c[i].index = i;//通过index可以避免在使用选择排序时直接把序号交换掉 
	}

	for (int i = 0; i < n - 1; ++i) {
		int tempmin = i;
		for (int j = i + 1; j < n; ++j) {
			//新病人老 
			if(c[j].age>=60){
				//在位病人老 
				if(c[tempmin].age>=60){
					if (c[j].age > c[tempmin].age){
						tempmin = j;
					}
					else if (c[j].age == c[tempmin].age) {
						if (c[j].index < c[tempmin].index) {
							tempmin = j;
						}
					}
				}
				//在位病人新 
				else {
					tempmin = j;
				}	
			}
		
			//新病人新 
			if(c[j].age<60){
				//在位病人新(在位病人老的情况无需排序) 
				if(c[tempmin].age<60){
					if (c[j].index < c[tempmin].index) {
						tempmin = j;
					}
				}
			}
	}//一定要注意这个括号的位置,对j循环结束之后再对换 
		Patient tmp = c[i];
		c[i] = c[tempmin];
		c[tempmin] = tmp;

	}

	for (int i = 0; i < n; ++i) {
		cout << c[i].id << endl;
	}

}

057 mysort

#include <iostream>
using namespace std;
struct A {
	int nouse1;
	int nouse2;
	int n;
};
	void mysort(void* a, int num, int width, int (*f)(const void* e1, const void* e2)){
		char* c = (char*)a;//形参的名字可以跟实参相同,且此时在函数内部改变形参,实参不会发生改变
		for (int i = 0; i < num - 1; ++i) {
			
			for (int j = i + 1; j < num; ++j) {
				//如果在位更大
				char* p1 =(char*) c + width * i;//数组在传参的时候是例外,所以对c排序,最后输出a也是排序后的 
				char* p2 =(char*) c + width * j;
				if (f(p1, p2) > 0) {
					//冒泡排序是对每个(i)位置找最小,传统选择排序是找j位置的最小 
					for (int k = 0; k < width; k++) {
						char tem = p1[k];//这个char换成int也行 
						p1[k] = p2[k];
						p2[k] = tem;
				    }
				}
			}


		}
	}
int MyCompare1( const void * e1,const void * e2) 
{
	int * p1 = (int * ) e1;
	int * p2 = (int * ) e2;
	return * p1 - * p2;
}
int MyCompare2( const void * e1,const void * e2) 
{
	int * p1 = (int * ) e1;
	int * p2 = (int * ) e2;
	if( (* p1 %10) - (* p2 % 10))
		return (* p1 %10) - (* p2 % 10);
	else
		return * p1 - * p2;
}
int MyCompare3( const void * e1,const void * e2) 
{
	A * p1 = (A*) e1;
	A * p2 = (A*) e2;
	return p1->n - p2->n;
}
int a[20];
A b[20];
int main ()
{	
	int n;
	while(cin >> n) {
		for(int i = 0;i < n; ++i) {
			cin >> a[i];
			b[i].n = a[i];
		}
		mysort(a,n,sizeof(int),MyCompare1);
		for(int i = 0;i < n; ++i) 
			cout << a[i] << "," ;
		cout << endl;
		mysort(a,n,sizeof(int),MyCompare2);
		for(int i = 0;i < n; ++i) 
			cout << a[i] << "," ;
		cout << endl;
		mysort(b,n,sizeof(A),MyCompare3);
		for(int i = 0;i < n; ++i) 
			cout << b[i].n << "," ;
		cout << endl;
	}
	return 0;
}

058 从字符串中取数

#include <iostream>
#include <iomanip>
using namespace std;
double GetDoubleFromString(char * str)
{
static char* start;
	
	if(str){
		start=str;
	}
	//跳过非数字 
	while(*start&&(*start<'0'||*start>'9')){
		++start;
	}
	if(*start==0){
		return NULL;
	}
	//遇到数字
	double numble=0;
	while(*start&&(*start>='0'&&*start<='9')){
		numble=numble*10+(*start-'0');
		++start; 
	}
	//遇到小数点
	double i=10;
	if(*start=='.'){//注意此时不能写while,低级的错误 
		++start;
		while(*start&&(*start>='0'&&*start<='9')){//其实*start可以不用写了 
			numble=numble+(*start-'0')/i;
			++start; 
			i*=10;
	}
	} 

	return numble;
}

int main()
{
	char line[300];
	while(cin.getline(line,280)) {
		double n;
		n = GetDoubleFromString(line);
		while( n > 0) {
			cout << fixed << setprecision(6) << n << endl;
			n = GetDoubleFromString(NULL);
		}
	}
	return 0;
}

059 sort简单题

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

int main()
{
	int a[8] = {6,5,14,23,2,9,87,10 };
	sort(
a+1,a+7,greater<int>()
);
	for(int i = 0;i < 8; ++i)
		cout << a[i] << "," ; 
	return 0;
}

060 还是sort简单题

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

struct Point{
	int x;
	int y;
};
struct Rule1
{
	bool operator()(const int& a1, const int& a2) const {
		if (a1 % 10 != a2 % 10) {
			return a1 % 10 < a2 % 10;
		}
		else {
			return a1 > a2;
		}
	}
};
struct Rule2
{
	bool operator()(const Point& a1, const Point& a2) const {
		int l1 = a1.x * a1.x + a1.y * a1.y;
		int l2 = a2.x * a2.x + a2.y * a2.y;
		if (l1 != l2) {
			return l1 < l2;
		}
		else {
			if (a1.x != a2.x)
				return a1.x < a2.x;
			else
				return a1.y < a2.y;
		}
	}
};

int main()
{
	int a[8] = {6,5,55,23,3,9,87,10 };
	sort(a,a+8,Rule1());
	for(int i = 0;i < 8; ++i)
		cout << a[i] << "," ; 
	cout << endl;
	Point ps[8] = {{1,0},{0,1},{0,-1},{-1,0},{1,-1},{1,1},{2,0},{-2,0} } ;
	sort(ps,ps+8,Rule2());
	for(int i = 0;i < 8; ++i)
		cout << "(" << ps[i].x << "," << ps[i].y << ")"; 
	return 0;
}

061 Set

#include<iostream>
#include<string>
#include<set>
#include<iterator>

using namespace std;
int main(){
	multiset<int> mset;
	set<int> sset;
	char command[5];
	int n,num;
	multiset<int>::iterator it;
	cin>>n;
	for(int i=0;i<n;++i){
		cin>>command>>num;
		switch(command[1]){
		case 'd':
			mset.insert(num);
			sset.insert(num);
			cout<<mset.count(num)<<endl;
			break;
		case 'e':
			cout<<mset.count(num)<<endl;
			mset.erase(num);
			break;
		case 's':
			if(sset.find(num)==sset.end())
				cout<<"0 0"<<endl;
			else{
				cout<<"1 ";
				cout<<mset.count(num)<<endl;
			}
			break;	 
		}
	}
	
	return 0;
	
}

062 热血格斗场

#include<iostream>
#include<set>
#include<map>
#include<iterator>
using namespace std;

struct Member{
	int zhanli;
	int id;
}member;
typedef map<int,int> MP;//保证两人的战力不同 

int main(){
	MP mp;
	int n;
	//添加facer 
	member.id=1;
	member.zhanli=1000000000;
	mp.insert(make_pair(member.zhanli,member.id));
	
	cin>>n;
	while(n--){
		cin>>member.id>>member.zhanli;
		//先在现有map里找一个插入点,在一般情况下lower_bound找到的指针指向插入点+1位置
		MP::iterator di=mp.lower_bound(member.zhanli);
		MP::iterator gao;
		//一般情况,即是在map中间插入 
		if(di!=mp.begin()){//如果不是最弱的	
			if(di!=mp.end()){//如果不是最强的 
				gao=di;
				--di;//此时gao是比插入位置相邻强一位,di是比插入位置相邻弱一位 
				
				//讨论前后差距,如果前面差距小
				if(member.zhanli-di->first>gao->first-member.zhanli){
					cout<<member.id<<" "<<gao->second<<endl;
				} 
				//讨论前后差距,如果后面差距小
				else if(member.zhanli-di->first<gao->first-member.zhanli){
					cout<<member.id<<" "<<di->second<<endl;
				}
				//讨论前后差距,如果前后一样 
				else if(member.zhanli-di->first==gao->first-member.zhanli){
					cout<<member.id<<" "<<di->second<<endl;
				}  		 
			}
			else{//如果是最强的
				--di;//因为end()返回值指向最后一个元素后面的迭代器 
				cout<<member.id<<" "<<di->second<<endl;
			}
		}
		else{//如果是最弱的
			cout<<member.id<<" "<<di->second<<endl; 
		}
		//插入新的member
		mp.insert(make_pair(member.zhanli,member.id));
	}
	return 0;
}

063 冷血格斗场

维护了一个有序队列,用multimap反而麻烦了。

#include<iostream>
#include<set>
#include<map>
#include<iterator>
using namespace std;

struct Member{
	int zhanli;
	int id;
}member;
typedef map<int,int> MP;//两人的实力值可以相同 

int main(){
	MP mp;//map<int, int> mp;其实不依赖struct,可以没有struct 
	int n;
	//添加facer 
	mp[1000000000] = 1;//也可以写作(1)mp.insert(pair<int, int>(10...,1));(2) mp[1000000000] = 1;仅map可以用 
	
	cin>>n;
	while(n--){
		cin>>member.id>>member.zhanli;
		//先在现有map里找一个插入点,在一般情况下lower_bound找到的指针指向插入点+1位置
		MP::iterator di=mp.lower_bound(member.zhanli);//另一种写法auto it = mp.lower_bound(value);      // 返回最小的大于等于value的迭代器 
		MP::iterator gao;
		//一般情况,即是在map中间插入 
		if(di!=mp.begin()){//如果不是最弱的	
			if(di!=mp.end()){//如果不是最强的 
				gao=di;
				--di;//此时gao是比插入位置相邻强一位,di是比插入位置相邻弱一位 
				
				//以下每种情况都要讨论 如果有多个人的实力值与他差别相同,则他会选择id最小的那个。
				//讨论前后差距,如果前面差距小
				if(member.zhanli-di->first>gao->first-member.zhanli){
					cout<<member.id<<" "<<gao->second<<endl;
				} 
				//讨论前后差距,如果后面差距小
				else if(member.zhanli-di->first<gao->first-member.zhanli){
					cout<<member.id<<" "<<di->second<<endl;
				}
				//讨论前后差距,如果前后一样
				else if(member.zhanli-di->first==gao->first-member.zhanli){
					if(gao->second<di->second)
						cout<<member.id<<" "<<gao->second<<endl;
					else
						cout<<member.id<<" "<<di->second<<endl;
				}  		 
			}
			else{//如果是最强的
				--di;//因为end()返回值指向最后一个元素后面的迭代器 
				cout<<member.id<<" "<<di->second<<endl;
			}
		}
		else{//如果是最弱的
			cout<<member.id<<" "<<di->second<<endl; 
		}
		//插入新的member,这样的操作维护了一个有序队列,始终让某个战力值的位置是id最小的人等待被挑战(其他人不可能在后续被挑战),所以可以用map,这是本题的核心 
		di=mp.find(member.zhanli);
		if(di==mp.end()||di->second>member.id)
			mp[member.zhanli]=member.id;
	}
	
	return 0;
}

结语

终于把C++的OpenJudge题目做完了上传上来了,这63个题目很有意思,本文可供参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值