算法基础知识——暴力求解

算法基础知识——暴力求解

目录:

  1. 基础知识
    1. 枚举
    2. 模拟(图形排版、日期、其他)
  2. 应用实例
    1. 反序数【清华大学】
    2. 对称平方数【清华大学】
    3. 与7无关的数【北京大学】
    4. 百钱买百鸡问题【华为机试】
    5. Old Bill【上海交通大学】
    6. 输出梯形【清华大学】
    7. 叠框【王道机试】
    8. Repeater【北京大学】
    9. Hello World for U【浙江大学】
    10. 今年的第几天?【清华大学】
    11. 打印日期【华中科技大学】
    12. 日期累加【北京理工大学】
    13. 日期差值【上海交通大学】
    14. Day of Week【上海交通大学】
    15. 日期类【北京理工大学】
    16. 剩下的树【清华大学】
    17. 手机键盘【清华大学】
    18. xxx定律【浙江大学】
    19. Grading【浙江大学】
    20. 路径打印【上海交通大学】
    21. 坠落的蚂蚁【北京大学】

一、基础知识

1、枚举

  • 枚举是指对每个可能的解进行逐一判断,直到找到符合题目要求的答案。

2、模拟

  • 模拟类题目在考研机试题目中出现频率很高,不涉及特别高深的知识,只需利用程序实现题目的要求。
  • 常见题型:
    • 图形排版:按照规定输出字符,主要考查对输出格式的把握。
    • 日期问题:把握问题题面的核心规律。
    • 其他模拟:类型多变。

二、应用实例

1、题目描述:设N是一个四位数,它的9倍恰好是其反序数(例如:1234的反序数是4321),求N的值。【清华大学】

  • 输入格式:程序无任何输入数据。
  • 输出格式:输出题目要求的四位数,如果结果有多组,则每组结果之间以回车隔开。
  • 样例输入:无
  • 样例输出:无

示例代码:

#include <iostream>

using namespace std;

int main(){
	int tmp, answer;
	for(int i = 1000; i <= 1111; i++){
		answer = 0, tmp = i;
		while(tmp != 0){
			answer = answer * 10 + tmp % 10;
			tmp /= 10;
		}
		if(i * 9 == answer){
			cout << i << endl;
		}
	}

	return 0;
}

2、题目描述:打印所有不超过256,其平方具有对称性质的数。如2,11就是这样的数,因为2*2=4,11*11=121。【清华大学】

  • 输入格式:无输入
  • 输出格式:输出具有题目要求的性质的数。如果输出数据不止一组,各组数据之间以回车隔开。
  • 样例输入:无
  • 样例输出:无

示例代码:

#include <iostream>

using namespace std;

int main(){
	int answer, tmp;
	for(int i = 0; i <= 256; i++){
		tmp = i * i, answer = 0;
		while(tmp != 0){
			answer = answer * 10 + tmp % 10;
			tmp /= 10;
		}
		if(answer == i * i){
			cout << i << endl;
		}
	}
	return 0;
}

3、题目描述:一个正整数,如果它能被7整除,或者它的十进制表示法中某个位数上的数字为7, 则称其为与7相关的数.现求所有小于等于n(n<100)的与7无关的正整数的平方和。【北京大学】

  • 输入格式:案例可能有多组。对于每个测试案例输入为一行,正整数n,(n<100)
  • 输出格式:对于每个测试案例输出一行,输出小于等于n的与7无关的正整数的平方和。
  • 样例输入:
    • 21
  • 样例输出:
    • 2336

示例代码:

#include <iostream>

using namespace std;

bool IsSevenRelate(int n){
	if(n % 7 == 0){
		return true;
	}
	while(n != 0){
		if(n % 10 == 7){
			return true;
		}
		n /= 10;
	}
	return false;
}

int main(){
	int N;
	while(cin >> N){
		int answer = 0;
		for(int i = 1; i <= N; i++){
			if(!IsSevenRelate(i)){
				answer += i * i;
			}
		}
		cout << answer << endl;
	}
	return 0;
}

4、题目描述:公元前五世纪,我国古代数学家张丘建在《算经》一书中提出了“百鸡问题”:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?
接口说明原型:int GetResult(vector &list):list  鸡翁、鸡母、鸡雏组合的列表(指针指向的内存区域保证有效),返回-1 失败,0 成功。【华为机试】

  • 输入格式:输入任何一个整数,即可运行程序。
  • 输出格式:鸡翁、鸡母、鸡雏组合的列表
  • 样例输入:
    • 1
  • 样例输出:
    • 0 25 75
    • 4 18 78
    • 8 11 81
    • 12 4 84

示例代码:

#include <iostream>
#include <vector>

using namespace std;

const double FATHER_PRICE = 5;
const double MOTHER_PRICE = 3;
const double CHILD_PRICE = 1/3.0;
const int TOTAL_MONEY = 100;

int GetResult(vector<int> &list){
	for(int i = 0; i <= TOTAL_MONEY / FATHER_PRICE; i++){
		for(int j = 0; j <= (TOTAL_MONEY - i * FATHER_PRICE) / MOTHER_PRICE; j++){
			for(int k = 0; k <= (TOTAL_MONEY - i * FATHER_PRICE - j * MOTHER_PRICE) / CHILD_PRICE; k++){
				if(i * FATHER_PRICE + j * MOTHER_PRICE + k * CHILD_PRICE == TOTAL_MONEY
					&& i + j + k == TOTAL_MONEY){
					list.push_back(i);
					list.push_back(j);
					list.push_back(k);
				}
			}
		}
	}
	if(list.size() == 0){
		return -1;
	}else{
		return 0;
	}
}

int main(){
	int input;
	vector<int> list;
	while(cin >> input){
		GetResult(list);
		for(int i = 0; i < list.size(); i += 3){
			cout << list[i] << " " << list[i + 1] << " " << list[i + 2] << endl;
		}
		list.clear();
	}
	return 0;
}

5、题目描述:Among grandfather's papers a bill was found.     72 turkeys $_679_     The first and the last digits of the number that obviously represented the total price of those turkeys are replaced here by blanks (denoted _), for they are faded and are illegible. What are the two faded digits and what was the price of one turkey?     We want to write a program that solves a general version of the above problem.     N turkeys $_XYZ_     The total number of turkeys, N, is between 1 and 99, including both. The total price originally consisted of five digits, but we can see only the three digits in the middle. We assume that the first digit is nonzero, that the price of one turkeys is an integer number of dollars, and that all the turkeys cost the same price.     Given N, X, Y, and Z, write a program that guesses the two faded digits and the original price. In case that there is more than one candidate for the original price, the output should be the most expensive one. That is, the program is to report the two faded digits and the maximum price per turkey for the turkeys.【上海交通大学】

  • 输入格式:The first line of the input file contains an integer N (0<N<100), which represents the number of turkeys. In the following line, there are the three decimal digits X, Y, and Z., separated by a space, of the original price $_XYZ_.
  • 输出格式:For each case, output the two faded digits and the maximum price per turkey for the turkeys.
  • 样例输入:
    • 72
    • 6 7 9
    • 5
    • 2 3 7
    • 78
    • 0 0 5
  • 样例输出:
    • 3 2 511
    • 9 5 18475
    • 0

示例代码:

#include <iostream>

using namespace std;

const int MAX_PRICE = 99999;

int main(){
	int N, x, y, z;
	while(cin >> N){
		cin >> x >> y >> z;
		int tmp = x * 1000 + y * 100 + z * 10;
		int max_price = MAX_PRICE, result_i, result_j;
		for(int i = 1; i < 10; i++){
			for(int j = 0; j < 10; j++){
				if((tmp + i * 10000 + j) % N == 0 && N <= max_price){
					max_price = (tmp + i * 10000 + j) / N;
					result_i = i;
					result_j = j;
				}
			}
		}
		if(max_price != MAX_PRICE){
			cout << result_i << " " << result_j << " " << max_price << endl;
		}else{
			cout << 0 << endl;
		}
	}
	return 0;
}

6、输入一个高度h,输出一个高度为h,上底边长度为h的梯形。【清华大学】

  • 输入格式:一个整数h(1≤ h ≤ 1000)
  • 输出格式:h所对应的梯形
  • 样例输入:
    • 4
  • 样例输出:
    •          ****
    •       ******
    •    ********
    • **********

示例代码:

#include <iostream>

using namespace std;

int main(){
	int level, tmp;
	while(cin >> level){
		tmp = level;
		for(int i = 1; i <= level; i++){
			int space = 2 * (tmp - i), star = tmp + 2 * (i - 1);
			while(space != 0){
				cout << " ";
				space--;
			}
			while(star != 0){
				cout << "*";
				star--;
			}
			cout << endl;
		}
	}
	return 0;
}

7、题目描述:把一个大小差一圈的筐叠上去,使得从上往下看时,边筐花色交错。【王道机试】

  • 输入格式:输入是一个三元组,分别是:外筐尺寸n(n为满足0 < n < 80的奇整数),中心花色字符,外筐花色字符,后二者都为Ascii可见字符。
  • 输出格式:输出叠在一起的筐图案,中心花色与外筐花色字符从内层起交错相叠,多筐相叠时,最外筐的角总是被打磨掉,叠筐与叠筐之间应有一行空格。
  • 样例输入:
    • 11 B A
    • 5 @ W
  • 样例输出:
    •  AAAAAAAAA 
    • ABBBBBBBBBA
    • ABAAAAAAABA
    • ABABBBBBABA
    • ABABAAABABA
    • ABABABABABA
    • ABABAAABABA
    • ABABBBBBABA
    • ABAAAAAAABA
    • ABBBBBBBBBA
    •  AAAAAAAAA 
    •  
    •  @@@
    • @WWW@
    • @W@W@
    • @WWW@
    •  @@@

示例代码:

#include <iostream>

using namespace std;

const int MAX_N = 80;

char matrix[MAX_N][MAX_N];

int main(){
	int n;
	char middle, outside;
	bool first = true;
	while(cin >> n >> middle >> outside){
		if(first){
			first = false;
		}else{
			cout << endl;
		}
		//奇数圈为外筐字符(对应i为偶数),偶数圈为中心字符
		char current;
		for(int i = 0; i <= n/2; i++){
			if((n / 2 - i) % 2 == 1){
				current = outside;
			}else{
				current = middle;
			}
			for(int j = 0; j < n - i * 2; j++){
				matrix[i][i + j] = current; //上
				matrix[n - i - 1][i + j] = current; //下
				matrix[i + j][i] = current; //左
				matrix[i + j][n - i - 1] = current; //右
			}
		}
		if(n != 1){ //多筐相叠时,最外筐的角总是被打磨掉
			matrix[0][0] = matrix[0][n - 1] = matrix[n - 1][n - 1] = matrix[n - 1][0] = ' ';
		}
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				cout << matrix[i][j];
			}
			cout << endl;
		}
	}
	return 0;
}

8、题目描述:Harmony is indispensible in our daily life and no one can live without it----may be Facer is the only exception. One day it is rumored that repeat painting will create harmony and then hundreds of people started their endless drawing. Their paintings were based on a small template and a simple method of duplicating. Though Facer can easily imagine the style of the whole picture, but he cannot find the essential harmony. Now you need to help Facer by showing the picture on computer. You will be given a template containing only one kind of character and spaces, and the template shows how the endless picture is created----use the characters as basic elements and put them in the right position to form a bigger template, and then repeat and repeat doing that. Here is an example. # #  #      <-template # # So the Level 1 picture will be # #  # # # Level 2 picture will be # #     # #  #         # # #     # #      # #         #         # #   # #    # #  #        # # #    # #【北京大学】

  • 输入格式:The input contains multiple test cases.
    The first line of each case is an integer N, representing the size of the template is N*N (N could only be 3, 4 or 5).
    Next N lines describe the template.
    The following line contains an integer Q, which is the Scale Level of the picture.
    Input is ended with a case of N=0.
    It is guaranteed that the size of one picture will not exceed 3000*3000.
  • 输出格式:For each test case, just print the Level Q picture by using the given template.
  • 样例输入:
    • 3
    • # #
    •  # 
    • # #
    • 1
    • 3
    • # #
    •  # 
    • # #
    • 3
    • 4
    •  OO 
    • O  O
    • O  O
    •  OO 
    • 2
    • 0
  • 样例输出:
    • # #
       # 
      # #
      # #   # #         # #   # #
       #     #           #     # 
      # #   # #         # #   # #
         # #               # #   
          #                 #    
         # #               # #   
      # #   # #         # #   # #
       #     #           #     # 
      # #   # #         # #   # #
               # #   # #         
                #     #          
               # #   # #         
                  # #            
                   #             
                  # #            
               # #   # #         
                #     #          
               # #   # #         
      # #   # #         # #   # #
       #     #           #     # 
      # #   # #         # #   # #
         # #               # #   
          #                 #    
         # #               # #   
      # #   # #         # #   # #
       #     #           #     # 
      # #   # #         # #   # #
           OO  OO     
          O  OO  O    
          O  OO  O    
           OO  OO     
       OO          OO 
      O  O        O  O
      O  O        O  O
       OO          OO 
       OO          OO 
      O  O        O  O
      O  O        O  O
       OO          OO 
           OO  OO     
          O  OO  O    
          O  OO  O    
           OO  OO     
       

示例代码:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

char a[3000][3000];
char model[5][5];
int N, Q;

void dfs(int m, int x, int y){
	if(m == 1){
		for(int i = 0; i < N; i++){
			for(int j = 0; j < N; j++){
				a[x + i][j + y] = model[i][j];
			}
		}
	}else{
		int scale = (int)pow(N, m - 1);
		for(int i = 0; i < N; i++){
			for(int j = 0; j < N; j++){
				if(model[i][j] != ' '){
					dfs(m - 1, x + i * scale, y + j * scale);
				}
			}
		}
	}
}

void InitArray(int width){
	for(int i = 0; i < width; i++){
		for(int j = 0; j < width; j++){
			a[i][j] = ' ';
		}
	}
}

int main(){
	string str;
	while(cin >> N && N){
		getchar();
		for(int i = 0; i < N; i++){
			getline(cin, str);
			for(int j = 0; j < str.size(); j++){
				model[i][j] = str[j];
			}
		}
		cin >> Q;
		int width = (int)pow(N, Q);
		InitArray(width);
		dfs(Q, 0, 0);
		for(int i = 0; i < width; i++){
			for(int j = 0; j < width; j++){
				cout << a[i][j];
			}
			cout << endl;
		}
	}
	return 0;
}

附注:

(1)把原图形看做一个元素,在模板有图形的地方用这个元素替换。设模板大小是N*N,repeat后,最终图形的大小变成原来大小的(k*N*N) * (k*N*N)。

9、题目描述:Given any string of N (>=5) characters, you are asked to form the characters into the shape of U. For example, "helloworld" can be printed as: h  d e  l l  r lowo That is, the characters must be printed in the original order, starting top-down from the left vertical line with n1 characters, then left to right along the bottom line with n2 characters, and finally bottom-up along the vertical line with n3 characters. And more, we would like U to be as squared as possible -- that is, it must be satisfied that n1 = n3 = max { k| k <= n2 for all 3 <= n2 <= N } with n1 + n2 + n3 - 2 = N.【浙江大学】

  • 输入格式:There are multiple test cases.Each case contains one string with no less than 5 and no more than 80 characters in a line. The string contains no white space.
  • 输出格式:For each test case, print the input string in the shape of U as specified in the description.
  • 样例输入:
    • helloworld!
    • www.nowcoder.com
  • 样例输出:
    • h   !
      e   d
      l   l
      lowor
      w    m
      w    o
      w    c
      .    .
      n    r
      owcode

示例代码:

#include <iostream>
#include <string>

using namespace std;

int main(){
	string str;
	while(cin >> str){
		int avgSize = (str.size() + 2) / 3;
		int bottom = str.size() + 2 - avgSize * 2;
		int i = 0;
		for(i = 0; i < avgSize - 1; i++){
			cout << str[i];
			for(int j = 0; j < bottom - 2; j++){
				cout << " ";
			}
			cout << str[str.size() - 1 - i] << endl;
		}
		for(int tmp = i; tmp < bottom + i; tmp++){
			cout << str[tmp];
		}
		cout << endl;
	}
	return 0;
}

10、题目描述:输入年、月、日,计算该天是本年的第几天。【清华大学】

  • 输入格式:包括三个整数,年(1<=Y<=3000)、月(1<=M<=12)、日(1<=D<=31)。
  • 输出格式:输入可能有多组测试数据,对于每一组测试数据,输出一个整数,代表Input中的年、月、日对应本年的第几天。
  • 样例输入:
    • 1990 9 20
    • 2000 5 1
  • 样例输出:
    • 263
    • 122

示例代码:

#include <iostream>

using namespace std;

int monthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int main(){
	int Y, M, D;
	while(cin >> Y >> M >> D){
		int sumDay = 0;
		if((Y % 4 == 0 && Y % 100 != 0) || Y % 400 == 0){
			monthDay[2] = 29;
		}else{
			monthDay[2] = 28;
		}
		for(int i = 1; i <= M - 1; i++){
			sumDay += monthDay[i];
		}
		sumDay += D;
		cout << sumDay << endl;
	}
	return 0;
}

11、题目描述:给出年分m和一年中的第n天,算出第n天是几月几号。【华中科技大学】

  • 输入格式:输入包括两个整数y(1<=y<=3000),n(1<=n<=366)。
  • 输出格式:可能有多组测试数据,对于每组数据,按 yyyy-mm-dd的格式将输入中对应的日期打印出来。
  • 样例输入:
    • 2000 3
    • 2000 31
    • 2000 40
    • 2000 60
    • 2000 61
    • 2001 60
  • 样例输出:
    • 2000-01-03
    • 2000-01-31
    • 2000-02-09
    • 2000-02-29
    • 2000-03-01
    • 2001-03-01

示例代码:

#include <iostream>
#include <iomanip>

using namespace std;

int monthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int main(){
	int n, y;
	while(cin >> y >> n){
		if((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){
			monthDay[2] = 29;
		}else{
			monthDay[2] = 28;
		}
		int i = 1, day = 0;
		while(n > 0){
			n -= monthDay[i++];
		}
		day = monthDay[i - 1] + n;
		cout << y << "-" << setfill('0') << setw(2) << i - 1 << "-" << setfill('0') << setw(2) << day << endl;
	}
	return 0;
}

12、题目描述:设计一个程序能计算一个日期加上若干天后是什么日期。【北京理工大学】

  • 输入格式:输入第一行表示样例个数m,接下来m行每行四个整数分别表示年月日和累加的天数。
  • 输出格式:输出m行,每行按yyyy-mm-dd的个数输出。
  • 样例输入:
    • 1
    • 2008 2 3 100
  • 样例输出:
    • 2008-05-13

示例代码:

#include <iostream>
#include <iomanip>

using namespace std;

int monthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year;

int LeapYear(int y){
	if((y % 100 != 0 && y % 4 == 0) || y % 400 == 0){
		monthDay[2] = 29;
		return year = 366;
	}else{
		monthDay[2] = 28;
		return year = 365;
	}
}

int main(){
	int n, resultYear, m, d, add;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> resultYear >> m >> d >> add;
			LeapYear(resultYear);
			int hadThroughDay = 0;
			for(int j = 1; j < m; j++){
				hadThroughDay += monthDay[j];
			}
			hadThroughDay += d;
			int remainDay = LeapYear(resultYear) - hadThroughDay;
			if(remainDay - add < 0){ //add超过当年
				add -= remainDay;
				resultYear++;
				while(add > LeapYear(resultYear)){
					resultYear++;
					add -= LeapYear(resultYear);
				}
			}else{
				add += hadThroughDay;
			}
			int resultMonth = 0;
			while(add - monthDay[resultMonth] > 0){
				add -= monthDay[resultMonth];
				resultMonth++;
			}
			cout << setfill('0') << setw(4) << resultYear << "-"
				<< setfill('0') << setw(2) << resultMonth << "-"
				<< setfill('0') << setw(2) << add << endl;
		}
	}
	return 0;
}

13、题目描述:有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天【上海交通大学】

  • 输入格式:有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
  • 输出格式:每组数据输出一行,即日期差值
  • 样例输入:
    • 20110412
    • 20110422
  • 样例输出:
    • 11

示例代码:

#include <iostream>
#include <string>

using namespace std;

int monthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year = 365;

int IsLeapYear(int year){
	if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
		monthDay[2] = 29;
		return year = 366;
	}else{
		monthDay[2] = 28;
		return year = 365;
	}
}

int stringToInt(string s){
	int answer = 0;
	for(int i = 0; i < s.size(); i++){
		answer = answer * 10 + s[i] - '0';
	}
	return answer;
}

int main(){
	string s1, s2;
	while(cin >> s1 >> s2){
		if(s1 > s2){
			string tmp = s1;
			s1 = s2;
			s2 = tmp;
		}
		int year1, year2, month1, month2, day1, day2;
		year1 = stringToInt(s1.substr(0, 4));
		year2 = stringToInt(s2.substr(0, 4));
		month1 = stringToInt(s1.substr(4, 2));
		month2 = stringToInt(s2.substr(4, 2));
		day1 = stringToInt(s1.substr(6));
		day2 = stringToInt(s2.substr(6));
		int answer = 0;
		if(year1 == year2){
			IsLeapYear(year1);
			if(month1 == month2){
				answer = day2 - day1;
			}else{
				for(int i = month1; i < month2; i++){
					answer += monthDay[i];
				}
				answer = answer - day1 + day2;
			}
		}else{
			for(int i = year1; i < year2; i++){
				answer += IsLeapYear(i);
			}
			IsLeapYear(year1);
			for(int i = 1; i < month1; i++){
				answer -= monthDay[i];
			}
			answer -= day1;
			IsLeapYear(year2);
			for(int i = 1; i < month2; i++){
				answer += monthDay[i];
			}
			answer += day2;
		}
		answer += 1;
		cout << answer << endl;
	}
	return 0;
}

14、题目描述:We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400. For example, years 2004, 2180 and 2400 are leap. Years 2005, 2181 and 2300 are not leap. Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating.【上海交通大学】

  • 输入格式:There is one single line contains the day number d, month name M and year number y(1000≤y≤3000). The month name is the corresponding English name starting from the capital letter.
  • 输出格式:Output a single line with the English name of the day of week corresponding to the date, starting from the capital letter. All other letters must be in lower case.Month and Week name in Input/Output:
    January, February, March, April, May, June, July, August, September, October, November, December
    Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
  • 样例输入:
    • 9 October 2001
    • 14 October 2001
  • 样例输出:
    • Tuesday
    • Sunday

示例代码1:

#include <iostream>
#include <string>
#include <ctime>

using namespace std;

int MonthStringToInt(string s){
	if(s == "January"){
		return 1;
	}else if(s == "February"){
		return 2;
	}else if(s == "March"){
		return 3;
	}else if(s == "April"){
		return 4;
	}else if(s == "May"){
		return 5;
	}else if(s == "June"){
		return 6;
	}else if(s == "July"){
		return 7;
	}else if(s == "August"){
		return 8;
	}else if(s == "September"){
		return 9;
	}else if(s == "October"){
		return 10;
	}else if(s == "November"){
		return 11;
	}else if(s == "December"){
		return 12;
	}else{
		return 0;
	}
}

string IntToWeek(int i){
	if(i == 0){
		return "Monday";
	}else if(i == 1){
		return "Tuesday";
	}else if(i == 2){
		return "Wednesday";
	}else if(i == 3){
		return "Thursday";
	}else if(i == 4){
		return "Friday";
	}else if(i == 5){
		return "Saturday";
	}else if(i == 6){
		return "Sunday";
	}else{
		return "";
	}
}

int main(){
	int day, year;
	string mStr;
	while(cin >> day >> mStr >> year){
		int month = MonthStringToInt(mStr);
		if(month == 1 || month == 2){
			month += 12;
			year--;
		}
		int week = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7;
		cout << IntToWeek(week) << endl;
	}
	return 0;
}

示例代码2:

#include <iostream>
#include <string>

using namespace std;

string monthArray[13] = {"", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
string weekArray[8] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ""};
int monthDay[2][13] = {
	{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
	{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

bool IsLeapYear(int year){
	return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

int main(){
	int day, month, year;
	string inputMonth;
	while(cin >> day >> inputMonth >> year){
		for(int i = 1; i <= 12; i++){
			if(inputMonth == monthArray[i]){
				month = i;
				break;
			}
		}
		//1年1月1日,星期一
		int answer = 1;
		int day1 = 1, month1 = 1, year1 = 1;
		if(year1 < year || month1 < month || day1 < day){
			answer = 0;
			while(year1 < year){
				if(IsLeapYear(year1++)){
					answer += 366;
				}else{
					answer += 365;
				}
			}
			int row = IsLeapYear(year);
			for(int i = 0; i < month; i++){
				answer += monthDay[row][i];
			}
			answer += day;
		}
		cout << weekArray[answer % 7] << endl;
	}
	return 0;
}

附注:

(1)基姆拉尔森计算日期公式  w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7。在公式中有个与其他公式不同的地方:把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。
(2)以公元元年为参考,公元元年1月1日为星期一。

(3)左右对齐、保留小数位数设置、输出前导零

    int f1 = 502345, f2 = 246245465;
    //左对齐
    cout << setiosflags(ios::left) << setw(10) << f1 << endl << setw(10) << f2 << endl;
    //右对齐
    cout << setiosflags(ios::right) << setw(10) << f1 << endl << setw(10) << f2 << endl;
    double f3 = 123.4567;
    //保留2位小数
    cout << fixed << setprecision(2) << f3 << endl;
    //保留5位小数
    cout << fixed << setprecision(5) << f3 << endl;
    //输出前导0
    int f4 = 123, f5 = 3456;
    cout << setfill('0') << setw(5) << f4 << endl << setfill('0') << setw(5) << f5 << endl;

15、题目描述:编写一个日期类,要求按xxxx-xx-xx 的格式输出日期,实现加一天的操作。【北京理工大学】

  • 输入格式:输入第一行表示测试用例的个数m,接下来m行每行有3个用空格隔开的整数,分别表示年月日。测试数据不会有闰年。
  • 输出格式:输出m行。按xxxx-xx-xx的格式输出,表示输入日期的后一天的日期。
  • 样例输入:
    • 2
    • 1999 10 20
    • 2001 1 31
  • 样例输出:
    • 1999-10-21
    • 2001-02-01

示例代码:

#include <iostream>
#include <iomanip>

using namespace std;

int monthDay[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int main(){
	int day, month, year, n;
	while(cin >> n){
		for(int i = 0; i < n; i++){
			cin >> year >> month >> day;
			if(month == 12 && day == 31){
				month = 1;
				day = 1;
				year++;
			}else{
				if(day == monthDay[month]){
					day = 1;
					month++;
				}else{
					day++;
				}
			}
			cout << setfill('0') << setw(4) << year << "-"
				<< setfill('0') << setw(2) << month << "-"
				<< setfill('0') << setw(2) << day << endl;
		}
	}
	return 0;
}

16、题目描述:有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是座标原点,在每个整数座标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。     现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。     可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。【清华大学】

  • 输入格式:两个整数L(1<=L<=10000)和M(1<=M<=100)。接下来有M组整数,每组有一对数字。
  • 输出格式:可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
  • 样例输入:
    • 500 3
    • 100 200
    • 150 300
    • 470 471
  • 样例输出:
    • 298

示例代码:

#include <iostream>

using namespace std;

int main(){
	int totalTree, count;
	while(cin >> totalTree >> count){
		int treeArray[10010] = {0};
		int from, to;
		for(int i = 0; i < count; i++){
			cin >> from >> to;
			for(int j = from; j <= to; j++){
				treeArray[j] = 1;
			}
		}
		int answer = 0;
		for(int i = 0; i <= totalTree; i++){
			if(treeArray[i] == 0){
				answer++;
			}
		}
		cout << answer << endl;
	}
	return 0;
}

17、按照手机键盘输入字母的方式,计算所花费的时间 如:a,b,c都在“1”键上,输入a只需要按一次,输入c需要连续按三次。 如果连续两个字符不在同一个按键上,则可直接按,如:ad需要按两下,kz需要按6下 如果连续两字符在同一个按键上,则两个按键之间需要等一段时间,如ac,在按了a之后,需要等一会儿才能按c。 现在假设每按一次需要花费一个时间段,等待时间需要花费两个时间段。 现在给出一串字符,需要计算出它所需要花费的时间。【清华大学】

  • 输入格式:一个长度不大于100的字符串,其中只有手机按键上有的小写字母
  • 输出格式:输入可能包括多组数据,对于每组数据,输出按出Input所给字符串所需要的时间
  • 样例输入:
    • bob
    • www
  • 样例输出:
    • 7
    • 7

示例代码1:

#include <iostream>
#include <string>

using namespace std;

struct Alphabet{
	char alpha;
	int type;
	int count;
	Alphabet();
	Alphabet(char a, int t, int c):alpha(a), type(t),count(c){}
};

int main(){
	Alphabet alphaList[26]= {
		Alphabet('a', 1, 1),
		Alphabet('b', 1, 2),
		Alphabet('c', 1, 3),
		Alphabet('d', 2, 1),
		Alphabet('e', 2, 2),
		Alphabet('f', 2, 3),
		Alphabet('g', 3, 1),
		Alphabet('h', 3, 2),
		Alphabet('i', 3, 3),
		Alphabet('j', 4, 1),
		Alphabet('k', 4, 2),
		Alphabet('l', 4, 3),
		Alphabet('m', 5, 1),
		Alphabet('n', 5, 2),
		Alphabet('o', 5, 3),
		Alphabet('p', 6, 1),
		Alphabet('q', 6, 2),
		Alphabet('r', 6, 3),
		Alphabet('s', 6, 4),
		Alphabet('t', 7, 1),
		Alphabet('u', 7, 2),
		Alphabet('v', 7, 3),
		Alphabet('w', 8, 1),
		Alphabet('x', 8, 2),
		Alphabet('y', 8, 3),
		Alphabet('z', 8, 4),
	};
	string str;
	while(cin >> str){
		int count = 0;
		for(int i = 0; i < str.size(); i++){
			bool hasNextType = false;
			if(i != str.size() - 1){
				hasNextType = true;
			}
			for(int j = 0; j < 26; j++){
				if(str[i] == alphaList[j].alpha){
					count += alphaList[j].count;
					int nextType = 0;
					if(hasNextType){
						int first = j - 3 < 0 ? 0 : j - 3, after = j + 3 >= 26 ? 25 : j + 3;
						for(int k = first; k <= after; k++){
							if(str[i + 1] == alphaList[k].alpha){
								nextType = alphaList[k].type;
								break;
							}
						}
						if(nextType == alphaList[j].type){
							count += 2;
						}
					}
					break;
				}
			}
		}
		cout << count << endl;
	}
	return 0;
}

示例代码2:

#include <iostream>
#include <string>

using namespace std;

int alphabet[26] = {1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 4};
int aType[26] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8};

int main(){
	string str;
	while(cin >> str){
		int total = alphabet[str[0] - 'a'], type = aType[str[0] - 'a'];
		for(int i = 1; i < str.size(); i++){
			int tmp = aType[str[i] - 'a'];
			total += alphabet[str[i] - 'a'];
			if(tmp == type){
				total += 2;
			}
			type = tmp;
		}
		cout << total << endl;
	}
	return 0;
}

18、对于一个数n,如果是偶数,就把n砍掉一半;如果是奇数,把n变成 3*n+ 1后砍掉一半,直到该数变为1为止。     请计算需要经过几步才能将n变到1,具体可见样例。【浙江大学】

  • 输入格式:测试包含多个用例,每个用例包含一个整数n,当n为0 时表示输入结束。(1<=n<=10000)
  • 输出格式:对于每组测试用例请输出一个数,表示需要经过的步数,每组输出占一行。
  • 样例输入:
    • 3
    • 1
    • 0
  • 样例输出:
    • 5
    • 0

示例代码:

#include <iostream>

using namespace std;

int main(){
	int n;
	while(cin >> n && n){
		int count = 0;
		while(n != 1){
			if(n % 2 == 0){
				n /= 2;
			}else{
				n = (3 * n + 1) / 2;
			}
			count++;
		}
		cout << count << endl;
	}
	return 0;
}

19、题目描述: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 <iomanip>
#include <algorithm>

using namespace std;

int main(){
	double P, T, G1, G2, G3, GJ;//20 2 15 13 10 18
	while(cin >> P >> T >> G1 >> G2 >> G3 >> GJ){
		double result;
		if(abs(G1 - G2) <= T){
			result = (G1 + G2) /2;
		}else{
			double a1 = abs(G3 - G1), a2 = abs(G3 - G2);
			if(a1 <= T && !(a2 <= T)){
				result = (G1 + G3) /2;
			}else if(!(a1 <= T) && a2 <= T){
				result = (G3 + G2) /2;
			}else if(a1 <= T && a2 <= T){
				double tmp = max(G1, G2);
				result = max(tmp, G3);
			}else{
				result = GJ;
			}
		}
		cout << fixed << setprecision(1) << result << endl;
	}
	return 0;
}

20、题目描述:给你一串路径,譬如: a\b\c a\d\e b\cst d\ 你把这些路径中蕴含的目录结构给画出来,子目录直接列在父目录下面,并比父目录向右缩一格,就像这样: a   b     c   d      e b   cst d 同一级的需要按字母顺序排列,不能乱。【上海交通大学】

  • 输入格式:每个测试案例第一行为一个正整数n(n<=10)表示有n个路径,当n为0时,测试结束,接下来有n行,每行有一个字串表示一个路径,长度小于50。
  • 输出格式:输出目录结构,每一个测试样例的输出紧跟一个空行。
  • 样例输入:
    • 4
    • a\b\c
    • a\d\e
    • b\cst
    • d\
    • 0
  • 样例输出:
    • a
    •   b
    •     c
    •   d
    •     e
    • b
    •   cst
    • d

示例代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>

using namespace std;

vector<vector<string> > myVector;

string GetPath(string str, int &index){
	string result = "";
	while(isalpha(str[index])){
		result += str[index++];
	}
	return result;
}

int main(){
	string str;
	int n;
	while(cin >> n && n != 0){
		for(int m = 0; m < n; m++){
			cin >> str;
			int index = 0;
			vector<string> strArray;
			while(index != str.size()){
				if(isalpha(str[index])){
					string name = GetPath(str, index);
					strArray.push_back(name);
				}else{
					index++;
				}
			}
			myVector.push_back(strArray);
		}
		sort(myVector.begin(), myVector.end());
		for(int i = 0; i < myVector.size(); i++){
			int maxDeepth = 0;
			//打印前找到最深的子目录位置
			if(i != 0){
				int childCount = myVector[i].size(), fatherCount = myVector[i - 1].size();
				int fatherTmp = 0, childTmp = 0;
				while(fatherTmp < fatherCount && childTmp < childCount
					&& myVector[i - 1][fatherTmp] == myVector[i][childTmp]){
					maxDeepth++;
					fatherTmp++;
					childTmp++;
				}
			}
			for(int j = maxDeepth; j < myVector[i].size(); j++){
				for(int k = 0; k < j; k++){
					cout << "  ";
				}
				cout << myVector[i][j] << endl;
			}
		}
		cout << endl;
		myVector.clear();
	}
	return 0;
}

21、题目描述:一根长度为1米的木棒上有若干只蚂蚁在爬动。它们的速度为每秒一厘米或静止不动,方向只有两种,向左或者向右。如果两只蚂蚁碰头,则它们立即交换速度并继续爬动。三只蚂蚁碰头,则两边的蚂蚁交换速度,中间的蚂蚁仍然静止。如果它们爬到了木棒的边缘(0或100厘米处)则会从木棒上坠落下去。在某一时刻蚂蚁的位置各不相同且均在整数厘米处(即1,2,3,…99厘米),有且只有一只蚂蚁A速度为0,其他蚂蚁均在向左或向右爬动。给出该时刻木棒上的所有蚂蚁位置和初始速度,找出蚂蚁A从此时刻到坠落所需要的时间。【北京大学】

  • 输入格式:第一行包含一个整数表示蚂蚁的个数N(2<=N<=99),之后共有N行,每一行描述一只蚂蚁的初始状态。每个初始状态由两个整数组成,中间用空格隔开,第一个数字表示初始位置厘米数P(1<=P<=99),第二个数字表示初始方向,-1表示向左,1表示向右,0表示静止。
  • 输出格式:蚂蚁A从开始到坠落的时间。若不会坠落,输出“Cannot fall!”
  • 样例输入:
    • 4
    • 10 1
    • 90 0
    • 95 -1
    • 98 -1
  • 样例输出:
    • 98

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Ant{
	int position;
	int direct;
	Ant(int p, int d):position(p), direct(d){};
	bool operator<(const Ant &ant){
		return position < ant.position;
	}
};

vector<Ant> myVector;

int main(){
	int n;
	while(cin >> n){
		int pos, dir, zeroLoc = 0, leftCount = 0;
		for(int i = 0; i < n; i++){
			cin >> pos >> dir;
			if(dir == -1){
				leftCount++;
			}
			Ant ant(pos, dir);
			myVector.push_back(ant);
		}
		sort(myVector.begin(), myVector.end());
		for(int i = 0; i < myVector.size(); i++){
			if(myVector[i].direct == 0){
				zeroLoc = i;
			}
		}
		int answer = 0;
		if(leftCount ==  zeroLoc){
			answer = 0;
		}
		else if(leftCount > zeroLoc){ //向左走蚂蚁数量大于静止的蚂蚁左边蚂蚁数量,静止蚂蚁左边落下
			int count = 0;
			for(int i = 0; i < n; i++){
				if(myVector[i].direct == -1 && count == zeroLoc){
					answer = myVector[i].position;
					break;
				}else if(myVector[i].direct == -1){
					count++;
				}
			}
		}else{
			int count = n - 1;
			for(int i = n - 1; i >= 0; i--){
				if(myVector[i].direct == 1 && count == zeroLoc){
					answer = 100 - myVector[i].position;
					break;
				}else if(myVector[i].direct == 1){
					count--;
				}
			}
		}
		if(answer == 0){
			cout << "Cannot fall!" << endl;
		}else{
			cout << answer << endl;
		}
	}
	return 0;
}

附注:

(1)只要静止的蚂蚁左边的蚂蚁数量,等于所有蚂蚁中往左走的数量,亦或者右边的等于向右走的那么它就不会掉下去。

(2)蚂蚁的相对位置不变,静止蚂蚁A的位置记为k,第k只蚂蚁掉下去,是树枝上左边k-1只都下去了,就是说一开始所有向左走的蚂蚁中,第k个蚂蚁要走多远,就是蚂蚁A坠落的时间。

参考文献:

[1]杨泽邦、赵霖. 计算机考研——机试指南(第2版). [M]北京:电子工业出版社,2019.11;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章