算法基礎知識——暴力求解

算法基礎知識——暴力求解

目錄:

  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;

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