第二章经典入门

1,排序

题目中如果没有要求,就可用sort,否则自定义排序函数。

具体实现见代码:sorting.cppscoressort.cpp

/**sorting.cpp:输入整数n,之后输入这n个整数,排序后,由小到大排出*****/
/**1,使用冒泡排序;2,使用sort排序;3,使用sort(begin, end, cmp)********/
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#define max 110
int buf[max];
void bubbleSort(int buf[], int n){//大石头依次落河
	int i, j, flag = 0;
	for(i = n; i >= 1; i--){
		flag = 0;
		for(j = 1; j <= i-1; j++){
			if(buf[j] > buf[j+1]){int tmp = buf[j+1]; buf[j+1] = buf[j]; buf[j] = tmp;flag = 1;}
		}
		if(!flag) return;
	}
}

int cmp(int a, int b){
	return a > b;
}

int main(){
	int n;
	while(cin >> n){
		int i;
		for(i = 1; i <= n; i++) cin >> buf[i];
		//bubbleSort(buf, n);
		//sort(buf+1, buf+1+n);
		sort(buf+1, buf+1+n, cmp);//由大到小排序
		for(i = 1; i <= n; i++) {
			if(i == 1) cout << buf[i];
			else cout << setw(2) << buf[i];
		}
		cout << endl;
	}
	return 0;
}

/***scoressort.cpp:输入n个学生数据并由小到大排序,排序规则依次比较顺序为:成绩,姓名,年龄*****/
/***定义结构体Stu,将数据存入数组Stu stu[max]中,自定义比较规则后,用sort排序后输出即可******/
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <string>
using namespace std;
#define max 110
struct Stu{
	int score;
	string name;
	int age;
	bool operator<(const Stu &a) const{
		if(score != a.score) return score < a.score; //必须采取return score < a.score;这种形式
		else if(name != a.name) return name < a.name;
		else return age < a.age;
	}
};
/*
bool cmp(const Stu &a, const Stu &b){
    if(a.score != b.score) return a.score < b.score;
	else if(a.name != b.name) return a.name < b.name;
	else return a.age < b.age;
}
sort(stu+1, stu+n+1, cmp);
*/
Stu stu[max];
int main(){
	int n;
	while(cin >> n){
		int i;
		for(i = 1; i <= n; i++)
			cin >> stu[i].name >> stu[i].age >> stu[i].score;
		sort(stu+1, stu+n+1);
		for(i = 1; i <= n; i++)
			cout << stu[i].name << setw(3) << stu[i].age << setw(3) << stu[i].score << endl;
	}
	return 0;
}

2,日期类问题

注意

a:使用三维数组buf[3001][13][32],下标表示年月日,内容表示从0年1日1日的开始计算的天数,即buf[0][1][3] = 3,这也是hash的基本思想;

b: 输入注重技巧,如输入20110412对应scanf中的%4d%2d%2d;

c: 将buf数组定义为全局变量或者用malloc等动态申请。

d: 当输入英文月份October时,可以用string数组存放,返回下标即为对应的月份,此后并可以上面a的思路开始分析;

e:如果问某个日期对应的是星期几,则可以以2016/3/28为星期一,然后计算所给日期与2016/3/28的差值,即可推算出所给日期对应星期几。

具体实现见代码:datedifference.cpp,dayofweek.cpp。

/***datedifference.cpp:输入两个8位字宽的日期数字,计算他们之间的差值****************/
/***以0年1月1日为第一天,依次类推,将第几天存到buf[3001][13][32]中,可在date结构体中创建nextDay函数,此外考虑闰年的影响****/
#include <cstdio>
#include <cstdlib>
using namespace std;
#define isleap(x) x%400 == 0 || (x%100 != 0 && x%4 == 0) ? 1:0//此句别写错
int dayofmonth[13][2] = {0, 0, 31, 31, 28, 29, 31, 31, 30, 30, 31, 31, 30, 30, 31, 31, 31, 31, 30, 30, 31, 31, 30, 30, 31, 31};
struct date{
	int year;
	int month;
	int day;
	void nextDay(){
		day++;
		if(day > dayofmonth[month][isleap(year)])
		{day = 1; month++;}
		if(month > 12)
		{month = 1; year++;}
	}
};
int buf[3001][13][32];

int main(){
	//初始化
	date tmp;
	tmp.year = 0; tmp.month = 1; tmp.day = 1;
	int cnt = 0;//运行就提示白框,说明可能有死循环
	while(tmp.year <= 3000){
		buf[tmp.year][tmp.month][tmp.day] = ++cnt;
		tmp.nextDay();
	}
	int y1, m1, d1, y2, m2, d2;
	while(scanf("%4d%2d%2d", &y1, &m1, &d1) != EOF){
		scanf("%4d%2d%2d", &y2, &m2, &d2);
		printf("%d\n", abs(buf[y1][m1][d1] - buf[y2][m2][d2]) +1);
	}
	return 0;
}
/***dayofweek.cpp:输入一行:日 英文月份 年,求该日期代表星期几***********/
/***与datedifference的改动:1,先将英文月份改为数字;2,以2016/3/28周一为参照*********/
#include <iostream>
#include <string>
using namespace std;
#define isleap(x) x%4==0 && x%400!=0 || x%100==0 ? 1:0
string dayofWeek[7] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Sutarday", "Sunday"};//Tuesday->two->周二
int dayofMonth[13][2] = {0, 0, 31, 31, 28, 29, 31, 31, 30, 30, 31, 31, 30, 30, 31, 31, 31, 31, 30, 30, 31, 31, 30, 30, 31, 31};
string monthName[13] = { " ", "January", "February", "March", "April", "May", "June", "July", "Augest", "September", "October", "November", "December"};
struct Date{
	int day;
	int month;
	int year;
	void nextDay(){
		day++;
		if(day > dayofMonth[month][isleap(year)]){
			day = 1;
			month++;
		}
		if(month > 12){
			month = 1;
			year++;
		}
	}
};
int buf[3001][13][32];
int main(){
	Date tmp;
	int cnt = 0;
	tmp.year = 0;
	tmp.month = tmp.day = 1;
	while(tmp.year <= 3000){
		buf[tmp.year][tmp.month][tmp.day] = ++cnt;
		tmp.nextDay();
	}
	//cout << buf[0][12][31];
	string mon;
	int y, m, d;
	while(cin >> d >> mon >> y){
		int i;
		for(i = 1; i <= 12; i++){
			if(mon == monthName[i]){
				m = i; break;
			}
		}
		if(i == 13) cout << "Please input correct month name....\n";
		cout << dayofWeek[(((buf[y][m][d] - buf[2016][3][28])%7 + 7)%7)] << endl;
	}
	return 0;
}

3,Hash的应用

将存储位置与数据本身对应起来,即数组下标即为数据大小,存储内容为数据对应的属性。

具体实现见代码:hashapplication.cpp和sorthash.cpp。

/*****hashapplication.cpp:读入n名学生的成绩,将获得某给定分数的学生人数输出****/
/*****每次读入一个分数x,就将其读入到hash[x]中,当读入指定分数a后,直接读出hash[a]即可********/
#include <iostream>
#include <iomanip>
using namespace std;
#define max 110

int hash1[110];
int main(){
	int n;
	while(cin >> n){
		int a, i;
		memset(hash1, 0 ,sizeof(int)*max); //不明确时加上::,当改成hash1又可以,原因在于有相关的系统函数
		for(i = 0; i < n; i++){
			cin >> a;
			hash1[a]++;
		}
		cin >> a;
		cout << "The number is: " << setw(2) << hash1[a] << endl;
	}
	return 0;
}

/*****sorthash.cpp:给你n个数,从大到小输出其中前m大的数,第一行输入n,m;第二行输入n个数,介于[-500000,500000]间的整数********/
/*****考虑到算法复杂度,若直接排序再输出,n很大时时间耗费大。建Hash[1000010],输出数同时计入hash中,最后i由大到小一次遍历输出,m变为0时跳出循环**/
#include <iostream>
#define offset 50000
using namespace std;
int Hash[100001];
int main(){
	int n, m;
	while(cin >> n >> m){
		int x, i;
		for(i = 0; i < n; i++){
			cin >> x;
			Hash[x+offset] = 1;
		}
		int flag = 1;  
		for(i = 100000; i >= 0 && m; i--){
			if(Hash[i]){
				if(flag) {cout << i - offset; flag = 0;}
				else cout << " " << i - offset;
				m--;
			}
		}
		cout << endl;
	}
	return 0;
}

4,排版题

1,输出梯形;2,输出叠框

具体实现见代码:trapezoid.cpp和stackframe.cpp。

/****trapezoid.cpp:输入一个整数,输出对应的梯形**************/
/****高为n,顶边为n,每加一层,长度累积2,则底边为l=n+2*(n-1),计算初始行应输入前j=l-n个空格,k=n个星号,之后每次累加2**************/
#include <iostream>
using namespace std;
int main(){
	int n;
	while(cin >> n){
		int i, k, l = n + 2*(n-1);
		int j = l - n;
		for(i = 0; i < n; i++){
			k = 0;
			while(k < j){cout << " "; k++;}
			while(k < l){cout << "*"; k++;}
			j -= 2;
			cout << endl;
		}
	}
	return 0;
}
/***stackframe.cpp:输入奇数尺寸,内外圈交错字符a,b。最内圈为a,之后类推,四角打磨*******/
/*****建一个二维数组,刚开始四角在buf[1][1],buf[1][n],buf[n][n],buf[n][1],之后每次遍历就移动四角直到n/2次。注意a,b选择和四角抹掉*******/
/*****对原程序进行改进,加入蛇形数,即每次沿着四条边向右-->向下-->向左-->向上进行遍历,每次沿一条边时注意起点位置***********/
#include <iostream> //#include <iomanip> 	cout.setf(ios::fixed); cout << setprecision(2)
using namespace std;
char buf[82][82];
int cnt[82][82];
int main(){
	int n;
	char a, b;
	while(cin >> n){
		cin >> a >> b; //注意别把char型数据命名成int
		int i, j;
		char c;
		/*for(i = 1; i <= (n+1)/2; i++){ //从(1,1)到(n,n),第二次就从(2,2)到(n-1,n-1),注意每次使j和n-i+1同时减1
			c = i % 2 == 0? a:b;
			for(j = i; j <= n-i+1; j++) {buf[i][j] = c; buf[j][n-i+1] = c; buf[n-i+1][j] = c; buf[j][i] = c;}
		}*/
		int count = 0;
		for(i = 1; i <= (n+1)/2; i++){
			c = i % 2 == 0? a:b;
			for(j = i; j <= n-i+1; j++) {buf[i][j] = c; cnt[i][j] = ++count;}
			for(j = i+1; j <= n-i+1; j++) {buf[j][n-i+1] = c; cnt[j][n-i+1] = ++count;}
			for(j = n-i+1-1; j >= i; j--) {buf[n-i+1][j] = c; cnt[n-i+1][j] = ++count;}
			for(j = n-i+1-1; j >= i+1; j--) {buf[j][i] = c; cnt[j][i] = ++count;}
		}
		/*buf[1][1] = ' ';
		buf[1][n] = ' ';
		buf[n][1] = ' ';
		buf[n][n] = ' ';*/
		for(i = 1; i <= n; i++){
			for(j = 1; j <= n; j++){
				cout << buf[i][j];
			}
			cout << endl;
		}
		for(i = 1; i <= n; i++){
			for(j = 1; j <= n; j++){
				if(j == 1) cout << cnt[i][j];
				else 
					cout << " " << cnt[i][j];
			}
			cout << endl;
		}
	}
	return 0;
}

5,查找

二分法查找,时间复杂度为O(nlogn)。

具体实现见代码:studentinfo.cpp。

/*****输入n个学生信息,进行m次学号查询,每次输出对应的学生信息,没有信息就输出No Answer!**********/
/*****先用结构体保存,之后对学号进行二分法查找,ans为对应标号,当仍为初值-1时输出no answer*******/
#include <iostream>
#include <string>
using namespace std;
struct Stu{
	string id;
	string name;
	string sex;
	int age;
};
Stu stu[1010];
int main(){
	int n, m;
	while(cin >> n && n != 0){
		int i, j;
		for(i = 0; i < n; i++){
			cin >> stu[i].id >> stu[i].name >> stu[i].sex >> stu[i].age;
		}
		cin >> m;
		while(m--){
			string str;
			cin >> str;
			int mid = n/2, top = n-1, base = 0, ans = -1;
			while(base <= top){ //注意此处必须加上<=号,否则程序会出错,因为有可能最后base和top指向同一元素
				if(stu[mid].id == str) { ans = mid; break;}
				else if(stu[mid].id < str) { base = mid + 1; mid = (base+top)/2;}
				else {top = mid - 1; mid = (base+top)/2;}
			}
			if(ans == -1) cout << "No Answer!" << endl;
			else 
				cout << stu[ans].id << " " << stu[ans].name << " " << stu[ans].sex << " "<< stu[ans].age << endl;
		}
	}
	return 0;
}

6,贪心算法

一种总是选择当前最好的选择,而不是从整体上把握。

具体实现见代码:fatmousetrade.cpp,和tvtime.cpp。

/*****fatmousetrade.cpp:m元钱,n种物品(每种都有三个属性:总共g磅,总价值v元,重/钱a磅/元),问花m元最多买多少磅物品*********/
/*****建立结构体,每次输入数据都建立起数据。排序后,优先购买性价比高的物品,买完后再买下一个性价比最高的物品******/
#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
struct Good{
	double g;
	double v;
	double ave;
	void competea(){
		ave = g/v;
	}
};
bool cmp(const Good &a, const Good &b) {
		return a.ave > b.ave;
}
Good good[110];
int main(){
	int m ,n;
	while(cin >> m >> n && m != -1){
		int i, j;
		for(i = 0; i < n; i++){
			cin >> good[i].g >> good[i].v;
			good[i].competea();
		}
		sort(good, good+n, cmp);
		double sum = 0.0;
		for(i = 0; i < n && m > 0; i++){
			if(m < good[i].v){
				sum += m * good[i].ave;
				m = 0;
			}
			else{
				sum += good[i].g;
				m -= good[i].v;
			}
		}
		cout.setf(ios::fixed);
		cout << setprecision(3) << sum << endl;
	}
	return 0;
}</span>
/***tvtime.cpp:输入整数n,之后n行数据,表示电视节目起始时间,求最多能看多少节目;输入n时结束输入***********/
/***要优先选择结束时间最早的节目,先按结束时间排序,之后进行条件判断(上一节目结束时间<下一节目开始时间)后累计*******/
#include <iostream>
#include <algorithm>
using namespace std;
struct Tvshow{
	int start;
	int end;
	bool operator<(const Tvshow & a) const{
		return end < a.end;
	}
}tvshow[110];
int main(){
	int n;
	while(cin >> n && n != 0){
		int i, j;
		for(i = 0; i < n ; i++)
			cin >> tvshow[i].start >> tvshow[i].end;
		sort(tvshow, tvshow+n);
		int ans = 1;
		int endtime = tvshow[0].end;
		for(i = 1; i < n; i++){
			if(endtime < tvshow[i].start){
				endtime = tvshow[i].end;
				ans++;
			}
		}
		cout << ans << endl;
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值