C++藍橋杯試題集基礎練習VIP BASIC 14-30思路解析及代碼

聲明:
本人代碼僅供參考,不代表是最優的解,甚至一些題解可能過於複雜,歡迎大佬們提意見~

BASIC-14 時間轉換

題目描述

問題描述
  給定一個以秒爲單位的時間t,要求用“H:M:S”的格式來表示這個時間。H表示時間,M表示分鐘,而S表示秒,它們都是整數且沒有前導的“0”。例如,若t=0,則應輸出是“0:0:0”;若t=3661,則輸出“1:1:1”。
輸入格式
  輸入只有一行,是一個整數t(0<=t<=86399)。
輸出格式
  輸出只有一行,是以“H:M:S”的格式所表示的時間,不包括引號。
樣例輸入
0
樣例輸出
0:0:0
樣例輸入
5436
樣例輸出
1:30:36

思路

一小時=3600秒;一分鐘=60秒。所以,以這兩個數爲界限討論t的範圍即可

代碼

#include<iostream>
using namespace std;

int main()
{
	int t = 0;
	int h = 0, m = 0, t1 = 0;//代表輸出的H,M,S
	cin >> t;
	if (t == 0)
	{
		cout << "0:0:0";
	}
	else if (t >= 3600)
	{
		h = t / 3600;
		m = (t - (3600 * h)) / 60;
		t1 = t - (3600 * h) - (m * 60);
		cout << h << ":" << m << ":" << t1;
	}
	else if (t < 3600 && t >= 60)
	{
		m = t / 60;
		t1 = t - m * 60;
		cout << 0 << ":" << m << ":" << t1;
	}
	else
	{
		cout << 0 << ":" << 0 << ":" << t;
	}
	return 0;
}

BASIC-15 字符串對比

題目描述

問題描述
  給定兩個僅由大寫字母或小寫字母組成的字符串(長度介於1到10之間),它們之間的關係是以下4中情況之一:
  1:兩個字符串長度不等。比如 Beijing 和 Hebei
  2:兩個字符串不僅長度相等,而且相應位置上的字符完全一致(區分大小寫),比如 Beijing 和 Beijing
  3:兩個字符串長度相等,相應位置上的字符僅在不區分大小寫的前提下才能達到完全一致(也就是說,它並不滿足情況2)。比如 beijing 和 BEIjing
  4:兩個字符串長度相等,但是即使是不區分大小寫也不能使這兩個字符串一致。比如 Beijing 和 Nanjing
  編程判斷輸入的兩個字符串之間的關係屬於這四類中的哪一類,給出所屬的類的編號。
輸入格式
  包括兩行,每行都是一個字符串
輸出格式
  僅有一個數字,表明這兩個字符串的關係編號
樣例輸入
BEIjing
beiJing
樣例輸出
3

思路

此題用if-else語句將不同的情況分開討論即可。

代碼

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

int Judge(string s1, string s2)
{
	if (s1.size() != s2.size())//長度不相等
	{
		return 1;
	}
	else//長度相等
	{
		if (s1 == s2)//字符串相同
		{
			return 2;
		}
		else
		{
		    //把兩個字符串都全部轉成小寫
			transform(s1.begin(), s1.end(), s1.begin(), ::tolower);//s1大寫轉小寫
			transform(s2.begin(), s2.end(), s2.begin(), ::tolower);//s2大寫轉小寫
			if (s1 == s2)
			{
				return 3;
			}
			else
			{
				return 4;
			}
		}
	}
}
int main()
{
	string s1;
	string s2;
	cin >> s1 >> s2;
	cout << Judge(s1, s2) << endl;
	return 0;
}

BASIC-16 分解質因數

題目描述

問題描述
  求出區間[a,b]中所有整數的質因數分解。
輸入格式
  輸入兩個整數a,b。
輸出格式
  每行輸出一個數的分解,形如k=a1a2a3…(a1<=a2<=a3…,k也是從小到大的)(具體可看樣例)
樣例輸入
3 10
樣例輸出
3=3
4=22
5=5
6=2
3
7=7
8=222
9=33
10=2
5
提示
  先篩出所有素數,然後再分解。
數據規模和約定
  2<=a<=b<=10000

思路

題目已經給出了提示,先篩選出質數,然後分解

代碼

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

bool IsPrime(int n)
{
	if (n == 1 || n == 2)
	{
		return true;
	}
	else
	{
		for (int i = 2; i <= sqrt(n); i++)
		{
			if (n%i == 0)
			{
				return false;
			}
		}
		return true;
	}
}

void Break(int n)
{
	while (n>1)
	{
		int i = 2;
		while (n%i)
		{
			i++;
		}
		while (n%i == 0)
		{
			cout << i;
			n /= i;
			if (n > 1)
			{
				cout << "*";
			}
			else
			{
				break;
			}
		}
	}
}

int main()
{
	int a = 0, b = 0;
	cin >> a >> b;
	for (int i = a; i <= b; i++)
	{
		//篩選素數
		if (IsPrime(i))
		{
			cout << i << "=" << i;
		}
		else
		{
			cout << i << "=";
			Break(i);
		}
		cout << endl;

	}
	return 0;
}

BASIC-17 矩陣的乘法

題目描述

問題描述
  給定一個N階矩陣A,輸出A的M次冪(M是非負整數)
  例如:
  A =
  1 2
  3 4
  A的2次冪
  7 10
  15 22
輸入格式
  第一行是一個正整數N、M(1<=N<=30, 0<=M<=5),表示矩陣A的階數和要求的冪數
  接下來N行,每行N個絕對值不超過10的非負整數,描述矩陣A的值
輸出格式
  輸出共N行,每行N個整數,表示A的M次冪所對應的矩陣。相鄰的數之間用一個空格隔開
樣例輸入
2 2
1 2
3 4
樣例輸出
7 10
15 22

思路

本題主要要注意三點:1.要開闢三個二維數組,一個保存第一次輸入的矩陣元素值,一個用於保存每次相乘後的結果,最後一個是每一次更新的結果。2.相乘時需要寫一個三重循環。3.注意冪爲0時是對稱矩陣

代碼

#include<iostream>
using namespace std;
#define MAX 50
#include<string.h>

int main()
{
	int n = 0, m = 0;//階數和冪數
	int arr[MAX][MAX];
	int arr2[MAX][MAX];
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cin >> arr[i][j];
			arr2[i][j] = arr[i][j];
		}
	}
	while (m>1)
	{
		int temp[MAX][MAX];
		memset(temp, 0, sizeof(temp));

		/*核心*/
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					temp[i][j] += arr[i][k] * arr2[k][j];
				}
			}
		}

		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				arr[i][j] = temp[i][j];
			}
		}
		m--;
	}
	//0次冪
	if (m == 0)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (i == j)
				{
					arr[i][j] = 1;
				}
				else
				{
					arr[i][j] = 0;
				}
			}
		}
	}
	//打印
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << arr[i][j]<<" ";
		}
		cout << endl;
	}
	return 0;
}

BASIC-18 矩形面積交

題目描述

問題描述
  平面上有兩個矩形,它們的邊平行於直角座標系的X軸或Y軸。對於每個矩形,我們給出它的一對相對頂點的座標,請你編程算出兩個矩形的交的面積。
輸入格式
  輸入僅包含兩行,每行描述一個矩形。
  在每行中,給出矩形的一對相對頂點的座標,每個點的座標都用兩個絕對值不超過10^7的實數表示。
輸出格式
  輸出僅包含一個實數,爲交的面積,保留到小數後兩位。
樣例輸入
1 1 3 3
2 2 4 4
樣例輸出
1.00

思路

這個題目畫圖即可,圍成的面積一定是個矩形,找到該矩形的左下角座標和右上角座標,即可求出面積。

代碼

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

#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)

int main()
{
	double x1, y1, x2, y2, x3, y3, x4, y4;
	double a1, b1, a2, b2 = 0;
	cin >> x1 >> y1 >> x2 >> y2;
	cin >> x3 >> y3 >> x4 >> y4;

	//左下角橫座標a1與縱座標a2,
  //橫:先都找到最小的(最左方),再找這兩個中最大的(最右方)
  //縱:先都找到最小的(最下方),再找這兩個中最大的(最上方)
	a1 = max(min(x1, x2), min(x3, x4));
	b1 = max(min(y1, y2), min(y3, y4));

	//右上角橫座標a2與縱座標b2,
  //橫:先都找到最大的(最右方),再找這兩個中最小的(最左方)
  //縱:先都找到最大的(最上方),再找這兩個中最小的(最下方)
	a2 = min(max(x1, x2), max(x3, x4));
	b2 = min(max(y1, y2), max(y3, y4));

	if (a2 > a1&&b2 > b1)
	{
		cout << fixed<< setprecision(2) << (a2 - a1)*(b2 - b1);//注意不要忘記fixed
	}
	else
	{
		cout << fixed << setprecision(2) << 0.00;
	}
	return 0;
}

BASIC-19 完美的代價

題目描述

問題描述
  迴文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認爲迴文串纔是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
  交換的定義是:交換兩個相鄰的字符
  例如mamad
  第一次交換 ad : mamda
  第二次交換 md : madma
  第三次交換 ma : madam (迴文!完美!)
輸入格式
  第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
  第二行是一個字符串,長度爲N.只包含小寫字母
輸出格式
  如果可能,輸出最少的交換次數。
  否則輸出Impossible
樣例輸入
5
mamad
樣例輸出
3

思路

首先弄清楚Ipossible的兩種情況:(len代表字符串長度)
1.len爲奇數,有一個字符出現次數爲奇數,則不可能再有另外一個字符出現次數爲奇數
2.len爲偶數,則不可能有一個字符出現次數爲奇數
然後進行兩頭遍歷,設置三個下標變量,一個從頭開始,往後到倒數第二個字符結束,叫頭下標。一個從最後一個開始,往前,找與頭下標相同的字符,到與第一個下標相遇時結束,叫移動下標。一個是尾部下標,代表每次找到相同字符後要交換到的位置。
1.len爲偶數,對於每一個頭下標,移動下標往前找第一個和它相同的字符,若找到,就將找到的字符交換到尾部下標指向的地方,每遍歷一次,尾部下標都要往前挪一步;下一次從第二個字符開始,從尾部下標當前位置(即倒數第二個字符)往前找,重複
2. len 爲奇數,將唯一出現次數爲奇數的字符交換到中間位置需要交換的次數,累加到count中,交換完剩下字符輸出count即可

代碼

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

int main()
{
	int len = 0;
	cin >> len;
	string s;
	cin >> s;
	int flag = 0;//是否有第二個字符出現次數爲奇數
	int count = 0;
	int end = len - 1;
	for (int i = 0; i < end; i++)//遍歷到倒數第二個字符
	{
		for (int j = end; j >= i; j--)
		{
			if (i == j)//沒找到相同,說明有字符出現次數爲奇數
			{
				if (len % 2 == 0 || flag == 1)
				{
					cout << "Impossible" << endl;
					exit(0);
				}
				flag = 1;
				count += len / 2 - i;//直接加上將該唯一出現次數爲奇數的字符交換到中間所用的次數,後面的交換都相當於將該字符撇開不看
			}
			else if (s[i] == s[j])//找到相同字符
			{
				for (int k = j; k < end; k++)
				{
					swap(s[k], s[k + 1]);
					count++;
				}
				end--;
				break;
			}

		}
	}
	cout << count;
	return 0;
}

BASIC-20 數的讀法

問題描述

問題描述
  Tom教授正在給研究生講授一門關於基因的課程,有一件事情讓他頗爲頭疼:一條染色體上有成千上萬個鹼基對,它們從0開始編號,到幾百萬,幾千萬,甚至上億。
  比如說,在對學生講解第1234567009號位置上的鹼基時,光看着數字是很難準確的念出來的。
  所以,他迫切地需要一個系統,然後當他輸入12 3456 7009時,會給出相應的念法:
  十二億三千四百五十六萬七千零九
  用漢語拼音表示爲
  shi er yi san qian si bai wu shi liu wan qi qian ling jiu
  這樣他只需要照着念就可以了。
  你的任務是幫他設計這樣一個系統:給定一個阿拉伯數字串,你幫他按照中文讀寫的規範轉爲漢語拼音字串,相鄰的兩個音節用一個空格符格開。
  注意必須嚴格按照規範,比如說“10010”讀作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”讀作“shi wan”而不是“yi shi wan”,“2000”讀作“er qian”而不是“liang qian”。
輸入格式
  有一個數字串,數值大小不超過2,000,000,000。
輸出格式
  是一個由小寫英文字母,逗號和空格組成的字符串,表示該數的英文讀法。
樣例輸入
1234567009
樣例輸出
shi er yi san qian si bai wu shi liu wan qi qian ling jiu

代碼

#include <iostream>
#include <climits>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
	char a[12];//要輸入的數組
	char b[10][10] = { "ling","yi","er","san","si","wu","liu","qi","ba","jiu" };//個位數讀法
	char c[10][10] = { "","shi","bai","qian","wan","shi","bai","qian","yi","shi" };//除個位數讀法
	while (cin >> a)
	{
		int cnt = strlen(a);//看看輸入的數是幾位數
		int i = 0;//計數器,循環cnt次
		int j = 0;//判斷條件,判斷"shi"前面是否要加"yi"
		while (i < cnt)
		{
			if (a[i] - '0' != 0)
			{
				if (cnt == 10 && a[i] - '0' == 1 && j == 0)//如果是十幾億
				{
					cout << c[cnt - i - 1] << " ";
					j++;
				}
				else if (cnt == 6 && a[i] - '0' == 1 && j == 0)//如果是十幾萬
				{
					cout << c[cnt - i - 1] << " ";
					j++;
				}
				else
				{
					cout << b[a[i] - '0'] << " " << c[cnt - i - 1] << " ";
				}
			}
			if (a[i] - '0' == 0)
			{
				if (a[i] - '0' == 0 && a[i + 1] - '0' > 0)
					cout << b[a[i] - '0'] << " ";//會被讀成ling,要改成>
			}
			i++;
		}
	}
	return 0;
}

BASIC-21 Sine之舞

問題描述

問題描述
  最近FJ爲他的奶牛們開設了數學分析課,FJ知道若要學好這門課,必須有一個好的三角函數基本功。所以他準備和奶牛們做一個“Sine之舞”的遊戲,寓教於樂,提高奶牛們的計算能力。
  不妨設
  An=sin(1–sin(2+sin(3–sin(4+…sin(n))…)
  Sn=(…(A1+n)A2+n-1)A3+…+2)An+1
  FJ想讓奶牛們計算Sn的值,請你幫助FJ打印出Sn的完整表達式,以方便奶牛們做題。
輸入格式
  僅有一個數:N<201。
輸出格式
  請輸出相應的表達式Sn,以一個換行符結束。輸出中不得含有多餘的空格或換行、回車符。
樣例輸入
3
樣例輸出
((sin(1)+3)sin(1–sin(2))+2)sin(1–sin(2+sin(3)))+1

思路

先求得an,可以先把a1,a2,a3求出來觀察通項特徵
a1=sin(1)
a2=sin(1-sin(2))
a3=sin(1-sin(2+sin(3)))
再通過an求得sn即可,也可以先求出s1,s2,s3
s1=(a1)+1
s2=(a1+2)a2+1
s3=((a1+3)a2+2)a3+1
另外注意括號的輸入

代碼

#include<iostream>
using namespace std;

void An(int n)
{
	for (int i = 1; i <= n; i++)
	{
		cout << "sin(" << i;
		if (i != n)
		{
			if (n % 2 == 1)//奇數---注意代表的是前一個數字
			{
				cout << "-";
			}
			else
			{
				cout << "+";
			}
		}
		else
		{
			for (int i = 0; i < n; i++)//輸出剩下的n個右括號
			{
				cout << ")";
			}
		}
	}
}

void Sn(int n)
{
	for (int i = 1; i < n; i++)//先輸出前面的左括號
	{
		cout << "(";
	}
	for (int i = 1; i <= n; i++)
	{
		An(i);
		cout << "+" << n - i + 1;
		if (i != n)
		{
			cout << ")";
		}
	}
}
int main()
{
	int n = 0;
	cin >> n;
	Sn(n);
	return 0;
}

BASIC-22 FJ的字符串

問題描述

問題描述
  FJ在沙盤上寫了這樣一些字符串:
  A1 = “A”
  A2 = “ABA”
  A3 = “ABACABA”
  A4 = “ABACABADABACABA”
  … …
  你能找出其中的規律並寫所有的數列AN嗎?
輸入格式
  僅有一個數:N ≤ 26。
輸出格式
  請輸出相應的字符串AN,以一個換行符結束。輸出中不得含有多餘的空格或換行、回車符。
樣例輸入
3
樣例輸出
ABACABA

思路

本題觀察清楚數列AN的規律即可,規律不唯一,我找的規律是,將數列AN以string類型存儲,則站在字符串的角度:An+1=An+(下一個字母)+An,下一個字母可通過字母A運算得到。

代碼

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

int main()
{
	int n = 0;
	cin >> n;
	string res("A");
	char temp;
	if (n > 1)
	{
		for (int i = 1; i < n; i++)
		{
			temp = 'A' + i;
			res = res + temp + res;
		}
	}
	else //將第一種情況單拎出來,也可以合在一起
	{
		cout << res << endl;
		exit(0);
	}
	cout << res << endl;
	return 0;
}

BASIC-23 芯片測試

問題描述

問題描述
  有n(2≤n≤20)塊芯片,有好有壞,已知好芯片比壞芯片多。
  每個芯片都能用來測試其他芯片。用好芯片測試其他芯片時,能正確給出被測試芯片是好還是壞。而用壞芯片測試其他芯片時,會隨機給出好或是壞的測試結果(即此結果與被測試芯片實際的好壞無關)。
  給出所有芯片的測試結果,問哪些芯片是好芯片。
輸入格式
  輸入數據第一行爲一個整數n,表示芯片個數。
  第二行到第n+1行爲n*n的一張表,每行n個數據。表中的每個數據爲0或1,在這n行中的第i行第j列(1≤i, j≤n)的數據表示用第i塊芯片測試第j塊芯片時得到的測試結果,1表示好,0表示壞,i=j時一律爲1(並不表示該芯片對本身的測試結果。芯片不能對本身進行測試)。
輸出格式
  按從小到大的順序輸出所有好芯片的編號
樣例輸入
3
1 0 1
0 1 0
1 0 1
樣例輸出
1 3

思路

開闢一個新的數組count記錄每塊芯片對應的結果,如果第j塊芯片被查出是壞的,則count[j+1]- -,如果被查出來好,則count[j+1]++; 如果一塊芯片是好芯片,則它的要麼好的次數等於壞的次數,要麼好的次數大於壞的次數,所以只要count中該芯片編號對應位置大於0,就說明它是好芯片。

代碼

#include<iostream>
using namespace std;
#include<vector>
#define N  100

int main()
{
	int num = 0;
	cin >> num;
	int vv[N][N];
	for (int i = 0; i < num; i++)
	{
		for (int j = 0; j < num; j++)
		{
			cin >> vv[i][j];
		}
	}
	//給結果數組每個元素賦值
	vector<int> count(num + 1);
	for (int i = 0; i < count.size(); i++)
	{
		count[i] = 0;
	}
	//記錄好壞結果
	for (int i = 0; i < num; i++)
	{
		for (int j = 0; j < num; j++)
		{
			if (i != j)
			{
				if (vv[i][j] == 1)
				{
					count[j + 1]++;
				}
				else
				{
					count[j + 1]--;
				}
			}
		}
	}
	for (int i = 1; i < count.size(); i++)
	{
		if (count[i] >= 0)
		{
			cout << i << " ";
		}
	}
	system("pause");
	return 0;
}

BASIC-24 龜兔賽跑預測

題目描述

問題描述
  兔子與烏龜的比賽中,一旦任一秒結束後兔子發現自己領先t米或以上,它們就會停下來休息s秒。對於不同的兔子,t,s的數值是不同的,但是所有的烏龜卻是一致——它們不到終點決不停止。
  然而有些比賽相當漫長,全程觀看會耗費大量時間,而小華髮現只要在每場比賽開始後記錄下兔子和烏龜的數據——兔子的速度v1(表示每秒兔子能跑v1米),烏龜的速度v2,以及兔子對應的t,s值,以及賽道的長度l——就能預測出比賽的結果。但是小華很懶,不想通過手工計算推測出比賽的結果,於是他找到了你——清華大學計算機系的高才生——請求幫助,請你寫一個程序,對於輸入的一場比賽的數據v1,v2,t,s,l,預測該場比賽的結果。
輸入格式
  輸入只有一行,包含用空格隔開的五個正整數v1,v2,t,s,l,其中(v1,v2<=100;t<=300;s<=10;l<=10000且爲v1,v2的公倍數)
輸出格式
  輸出包含兩行,第一行輸出比賽結果——一個大寫字母“T”或“R”或“D”,分別表示烏龜獲勝,兔子獲勝,或者兩者同時到達終點。
  第二行輸出一個正整數,表示獲勝者(或者雙方同時)到達終點所耗費的時間(秒數)。
樣例輸入
10 5 5 2 20
樣例輸出
D
4
樣例輸入
10 5 5 1 20
樣例輸出
R
3
樣例輸入
10 5 5 3 20
樣例輸出
T
4

思路

兔子和烏龜走過的路程以每秒來計算比較,兔子領先t米時,讓烏龜所走距離加上烏龜速度乘以s秒,這裏一定要注意s秒內也要一秒一秒的比較,因爲烏龜有可能在s秒內就已經到達終點。
當兔子和烏龜所走路程有一個大於或等於l時,又或者同時大於或等於l時,則將標誌位設置爲不同結果即可。

代碼

#include<iostream>
using namespace std;

int main()
{
	int v1 = 0, v2 = 0, t = 0, s = 0, l = 0;
	cin >> v1 >> v2 >> t >> s >> l;
	int temp = 0;//當前經過的秒數
	int len1 = 0, len2 = 0;//兔子和烏龜當前所走的路程
	int flag = 0;//判斷誰贏標誌
	while (1)
	{
		temp++;
		len1 = len1 + v1 * 1;
		len2 = len2 + v2 * 1;
		if (len1 - len2 >= t && len1 < l)
		{
			for (int i = 1; i <= s; i++)
			{
				len2 += v2;
				temp += 1;
        //注意一定要考慮烏龜在s秒內可以走到終點的情況
				if (len2 >= l)
				{
					cout << "T" << endl;
					cout << temp;
					system("pause");
					exit(0);
				}
			}
		}

		if (len1 > len2 && len1 >= l)
		{
			flag = 1;
			break;
		}
		else if (len2 > len1 && len2 >= l)
		{
			flag = 2;
			break;
		}
		else if (len1 >= l && len2 >= l)
		{
			flag = 3;
			break;
		}
	}
	if (flag == 1)
	{
		cout << "R" << endl;
	}
	else if (flag == 2)
	{
		cout << "T" << endl;
	}
	else if (flag == 3)
	{
		cout << "D" << endl;
	}
	cout << temp << endl;
	return 0;
}

BASIC-25 回形取數

題目描述

問題描述
  回形取數就是沿矩陣的邊取數,若當前方向上無數可取或已經取過,則左轉90度。一開始位於矩陣左上角,方向向下。
輸入格式
  輸入第一行是兩個不超過200的正整數m, n,表示矩陣的行和列。接下來m行每行n個整數,表示這個矩陣。
輸出格式
  輸出只有一行,共mn個數,爲輸入矩陣回形取數得到的結果。數之間用一個空格分隔,行末不要有多餘的空格。
樣例輸入
3 3
1 2 3
4 5 6
7 8 9
樣例輸出
1 4 7 8 9 6 3 2 5
樣例輸入
3 2
1 2
3 4
5 6
樣例輸出
1 3 5 6 4 2

思路

一輪取數包括四個方向:下,右,上,左,依次遍歷取數。一輪取數結束後,如果取到的數小於數組元素個數,則繼續新一輪的取數。

代碼

#include<iostream>
using namespace std;
#include<vector>
#include<string.h>

#define N 200

int main()
{
	int row = 0;
	int col = 0;
	cin >> row >> col;
	int vv[N][N];
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			cin >> vv[i][j];
		}
	}

	int flag[N][N];
	memset(flag, 0, sizeof(flag));

	int i = 0;
	int j = 0;
	int count = 0;
	while (count < row*col)
	{
		//向下
		while (i < row && 0 == flag[i][j])//注意要將flag判別條件放在後面,因爲可能會有下標訪問越界,放後面利用短路避開
		{
			cout << vv[i][j] << " ";
			flag[i][j] = 1;
			i++;
			count++;
		}
		//此時i=row,所以要-1,
		i--;
		j++;
		//向右
		while (j < col && 0 == flag[i][j])
		{
			cout << vv[i][j] << " ";
			flag[i][j] = 1;
			j++;
			count++;
		}
		j--;
		i--;
	    //向上
		while (i >= 0 && 0 == flag[i][j])
		{
			cout << vv[i][j] << " ";
			flag[i][j] = 1;
			i--;
			count++;
		}
		i++;
		j--;
	    //向左
		while (j >= 0 && 0 == flag[i][j])
		{
			cout << vv[i][j] << " ";
			flag[i][j] = 1;
			j--;
			count++;
		}
		j++;
		i++;
	}
	return 0;
}

BASIC-26 報時助手

問題描述

問題描述
  給定當前的時間,請用英文的讀法將它讀出來。
  時間用時h和分m表示,在英文的讀法中,讀一個時間的方法是:
  如果m爲0,則將時讀出來,然後加上“o’clock”,如3:00讀作“three o’clock”。
  如果m不爲0,則將時讀出來,然後將分讀出來,如5:30讀作“five thirty”。
  時和分的讀法使用的是英文數字的讀法,其中0~20讀作:
  0:zero, 1: one, 2:two, 3:three, 4:four, 5:five, 6:six, 7:seven, 8:eight, 9:nine, 10:ten, 11:eleven, 12:twelve, 13:thirteen, 14:fourteen, 15:fifteen, 16:sixteen, 17:seventeen, 18:eighteen, 19:nineteen, 20:twenty。
  30讀作thirty,40讀作forty,50讀作fifty。
  對於大於20小於60的數字,首先讀整十的數,然後再加上個位數。如31首先讀30再加1的讀法,讀作“thirty one”。
  按上面的規則21:54讀作“twenty one fifty four”,9:07讀作“nine seven”,0:15讀作“zero fifteen”。
輸入格式
  輸入包含兩個非負整數h和m,表示時間的時和分。非零的數字前沒有前導0。h小於24,m小於60。
輸出格式
  輸出時間時刻的英文。
樣例輸入
0 15
樣例輸出
zero fifteen

思路

我的第一個思路是暴力,用switch case,將所有數字對應的英文全部寫出來,反正最多60個,努努力就出來了。
第二個思路是先獲取十位,用switch case輸出,將0~24的英文放在一個數組裏(因爲這個是公用的),後面的輸出從數組裏面拿元素就行

代碼

//方法一:笨辦法
#include<iostream>
using namespace std;
#include<string>
int main()
{
	int h = 0;
	int m = 0;
	string res;
	cin >> h >> m;
	switch (h)
	{
	case 0:
		res += "zero ";
		break;
	case 1:
		res += "one ";
		break;
	case 2:
		res += "two ";
		break;
	case 3:
		res += "three ";
		break;
	case 4:
		res += "four ";
		break;
	case 5:
		res += "five ";
		break;
	case 6:
		res += "six ";
		break;	
	case 7:
		res += "seven ";
		break;
	case 8:
		res += "eight ";
		break;
	case 9:
		res += "nine ";
		break;
	case 10:
		res += "ten ";
		break;
	case 11:
		res += "eleven ";
		break;
	case 12:
		res += "twelve ";
		break;
	case 13:
		res += "thirteen ";
		break;
	case 14:
		res += "fourteen ";
		break;
	case 15:
		res += "fifteen ";
		break;
	case 16:
		res += "sixteen ";
		break;
	case 17:
		res += "seventeen ";
		break;
	case 18:
		res += "eighteen ";
		break;
	case 19:
		res += "nineteen ";
		break;
	case 20:
		res += "twenty ";
		break;
	case 21:
		res += "twenty one ";
		break;
	case 22:
		res += "twenty two ";
		break;
	case 23:
		res += "twenty three ";
		break;
	default:
		break;
	}
	switch (m)
	{
	case 0:
		res += "o'clock";
		break;
	case 1:
		res += "one";
		break;
	case 2:
		res += "two";
		break;
	case 3:
		res += "three";
		break;
	case 4:
		res += "four";
		break;
	case 5:
		res += "five";
		break;
	case 6:
		res += "six";
		break;
	case 7:
		res += "seven";
		break;
	case 8:
		res += "eight";
		break;
	case 9:
		res += "nine";
		break;
	case 10:
		res += "ten";
		break;
	case 11:
		res += "eleven";
		break;
	case 12:
		res += "twelve";
		break;
	case 13:
		res += "thirteen";
		break;
	case 14:
		res += "fourteen";
		break;
	case 15:
		res += "fifteen";
		break;
	case 16:
		res += "sixteen";
		break;
	case 17:
		res += "seventeen";
		break;
	case 18:
		res += "eighteen";
		break;
	case 19:
		res += "nineteen";
		break;
	case 20:
		res += "twenty";
		break;
	case 21:
		res += "twenty one";
		break;
	case 22:
		res += "twenty two";
		break;
	case 23:
		res += "twenty three";
		break;
	case 24:
		res += "twenty four";
		break;
	case 25:
		res += "twenty five";
		break;
	case 26:
		res += "twenty six";
		break;
	case 27:
		res += "twenty seven";
		break;
	case 28:
		res += "twenty eight";
		break;
	case 29:
		res += "twenty nine";
		break;
	case 30:
		res += "thirty";
		break;
	case 31:
		res += "thirty one";
		break;
	case 32:
		res += "thirty two";
		break;
	case 33:
		res += "thirty three";
		break;
	case 34:
		res += "thirty four";
		break;
	case 35:
		res += "thirty five";
		break;
	case 36:
		res += "thirty six";
		break;
	case 37:
		res += "thirty seven";
		break;
	case 38:
		res += "thirty eight";
		break;
	case 39:
		res += "thirty nine";
		break;
	case 40:
		res += "forty";
		break;
	case 41:
		res += "forty one";
		break;
	case 42:
		res += "forty two";
		break;
	case 43:
		res += "forty three";
		break;
	case 44:
		res += "forty four";
		break;
	case 45:
		res += "forty five";
		break;
	case 46:
		res += "forty six";
		break;
	case 47:
		res += "forty seven";
		break;
	case 48:
		res += "forty eight";
		break;
	case 49:
		res += "forty nine";
		break;
	case 50:
		res += "fifty";
		break;
	case 51:
		res += "fifty one";
		break;
	case 52:
		res += "fifty two";
		break;
	case 53:
		res += "fifty three";
		break;
	case 54:
		res += "fifty four";
		break;
	case 55:
		res += "fifty five";
		break;
	case 56:
		res += "fifty six";
		break;
	case 57:
		res += "fifty seven";
		break;
	case 58:
		res += "fifty eight";
		break;
	case 59:
		res += "fifty nine";
		break;
	default:
		break;
	}
	cout << res << endl;
	return 0;
}

//方法二:
#include <iostream>
using namespace std;
int main() {
    int h, m;
    cin >> h >> m;
    string arr[24] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
					"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty one", "twenty two", "twenty three"};
	cout << arr[h] << " ";
    if (m == 0)
        cout << "o'clock";
    int t = m % 10;
    m = m / 10;
    switch(m) {
        case 2: cout << "twenty "; break;
        case 3: cout << "thirty "; break;
        case 4: cout << "forty "; break;
        case 5: cout << "fifty "; break;
        default: break;
    }
    if (m == 0 && t != 0) {
        cout << arr[t];
    }
    if (m == 1) {
        cout << arr[t + 10];
    }
    if (m != 0 && m != 1 && t!= 0) {
        cout << arr[t];
    }
    return 0;
}

BASIC-27 2n皇后問題

問題描述

問題描述
  給定一個n*n的棋盤,棋盤中有一些位置不能放皇后。現在要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行、同一列或同一條對角線上,任意的兩個白皇后都不在同一行、同一列或同一條對角線上。問總共有多少种放法?n小於等於8。
輸入格式
  輸入的第一行爲一個整數n,表示棋盤的大小。
  接下來n行,每行n個0或1的整數,如果一個整數爲1,表示對應的位置可以放皇后,如果一個整數爲0,表示對應的位置不可以放皇后。
輸出格式
  輸出一個整數,表示總共有多少种放法。
樣例輸入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
樣例輸出
2
樣例輸入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
樣例輸出
0

代碼
我用DFS嘗試沒有AC,這裏推薦一個個人覺得比較好懂的其他老鐵的遞歸寫法
(藍橋杯)基礎練習BASIC-27 2n皇后問題 (遞歸) C++

BASIC-28 Huffuman樹

題目描述

問題描述
  Huffman樹在編碼中有着廣泛的應用。在這裏,我們只關心Huffman樹的構造過程。
  給出一列數{pi}={p0, p1, …, pn-1},用這列數構造Huffman樹的過程如下:
  1. 找到{pi}中最小的兩個數,設爲pa和pb,將pa和pb從{pi}中刪除掉,然後將它們的和加入到{pi}中。這個過程的費用記爲pa + pb。
  2. 重複步驟1,直到{pi}中只剩下一個數。
  在上面的操作過程中,把所有的費用相加,就得到了構造Huffman樹的總費用。
  本題任務:對於給定的一個數列,現在請你求出用該數列構造Huffman樹的總費用。
  例如,對於數列{pi}={5, 3, 8, 2, 9},Huffman樹的構造過程如下:
  1. 找到{5, 3, 8, 2, 9}中最小的兩個數,分別是2和3,從{pi}中刪除它們並將和5加入,得到{5, 8, 9, 5},費用爲5。
  2. 找到{5, 8, 9, 5}中最小的兩個數,分別是5和5,從{pi}中刪除它們並將和10加入,得到{8, 9, 10},費用爲10。
  3. 找到{8, 9, 10}中最小的兩個數,分別是8和9,從{pi}中刪除它們並將和17加入,得到{10, 17},費用爲17。
  4. 找到{10, 17}中最小的兩個數,分別是10和17,從{pi}中刪除它們並將和27加入,得到{27},費用爲27。
  5. 現在,數列中只剩下一個數27,構造過程結束,總費用爲5+10+17+27=59。
輸入格式
  輸入的第一行包含一個正整數n(n<=100)。
  接下來是n個正整數,表示p0, p1, …, pn-1,每個數不超過1000。
輸出格式
  輸出用這些數構造Huffman樹的總費用。
樣例輸入
5
5 3 8 2 9
樣例輸出
59

思路

先將數組排序,確保最小的兩個數字在最前面,一個res用於記錄當前的費用,一個temp得到較小兩個數的和以後再插入到數組。如此循環,知道數組裏面只有一個元素的時候,輸出res就是當前的總費用。

代碼

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
vector<int> Change(vector<int> & v, int& result)
{
	int temp = 0;
    sort(v.begin(),v.end());
	temp = v[0] + v[1];
	result = result + v[0] + v[1];
	v.erase(v.begin(), v.begin() + 2);
	v.push_back(temp);
	return v;
}
int main()
{
	int len = 0;
	int result = 0;//費用
	cin >> len;
	vector<int> v(len);
	for (int i = 0; i < v.size(); i++)
	{
		cin >> v[i];
	}
	while (v.size()>1)
	{
		v = Change(v, result);
	}
	cout << result;
	return 0;
}

BASIC-29 高精度加法

題目描述

問題描述
  輸入兩個整數a和b,輸出這兩個整數的和。a和b都不超過100位。
算法描述
  由於a和b都比較大,所以不能直接使用語言中的標準數據類型來存儲。對於這種問題,一般使用數組來處理。
  定義一個數組A,A[0]用於存儲a的個位,A[1]用於存儲a的十位,依此類推。同樣可以用一個數組B來存儲b。
  計算c = a + b的時候,首先將A[0]與B[0]相加,如果有進位產生,則把進位(即和的十位數)存入r,把和的個位數存入C[0],即C[0]等於(A[0]+B[0])%10。然後計算A[1]與B[1]相加,這時還應將低位進上來的值r也加起來,即C[1]應該是A[1]、B[1]和r三個數的和.如果又有進位產生,則仍可將新的進位存入到r中,和的個位存到C[1]中。依此類推,即可求出C的所有位。
  最後將C輸出即可。
輸入格式
  輸入包括兩行,第一行爲一個非負整數a,第二行爲一個非負整數b。兩個整數都不超過100位,兩數的最高位都不是0。
輸出格式
  輸出一行,表示a + b的值。
樣例輸入
20100122201001221234567890
2010012220100122
樣例輸出
20100122203011233454668012

思路

利用String,將輸入的兩個數用string存儲。兩個字符串相應數位對應的數字字符轉換爲數字後進行相加並進位等一系列操作,結果存儲與vector數組後,從後往前輸出。

代碼

#include<iostream>
using namespace std;
#include<string>
#include<vector>
int main()
{
	string s1;
	string s2;
	cin >> s1 >> s2;
	int len = 0;
	int num = 0;
	int distance = 0;//代表兩個字符串的相差距離
	if (s1.size() >= s2.size())
	{
		len = s1.size();
		distance = s1.size() - s2.size();
	}
	else
	{
		len = s2.size();
		distance = s2.size() - s1.size();
	}
	//將短的字符串 相比於長的字符串相差的地方補'0',都變成長爲len的字符串
	if (distance)
	{
		if (s1.size() > s2.size())
		{
			for (int i = 0; i < distance; i++)
			{
				s2.insert(i, "0");
			}
		}
		else
		{
			for (int j = 0; j < distance; j++)
			{
				s1.insert(j, "0");
			}
		}
	}
	vector<int> res(len);
	for (int i = len-1; i  >=0; i--)//從後往前,依次將對應位的數字進行相加並進位
	{
		int temp = (s1[i] - '0') + (s2[i] - '0') + num;
		res[i] = temp % 10;
		num = temp / 10;
	}
	if (num)//注意最後一位可能會進位1
	{
		res.insert(res.begin(), 1);
	}
	for (int i = 0; i < res.size(); i++)
	{
		cout << res[i];
	}
	return 0;
}

BASIC-30 階乘計算

題目描述

問題描述
  輸入一個正整數n,輸出n!的值。
  其中n!=123*…*n。
算法描述
  n!可能很大,而計算機能表示的整數範圍有限,需要使用高精度計算的方法。使用一個數組A來表示一個大整數a,A[0]表示a的個位,A[1]表示a的十位,依次類推。
  將a乘以一個整數k變爲將數組A的每一個元素都乘以k,請注意處理相應的進位。
  首先將a設爲1,然後乘2,乘3,當乘到n時,即得到了n!的值。
輸入格式
  輸入包含一個正整數n,n<=1000。
輸出格式
  輸出n!的準確值。
樣例輸入
10
樣例輸出
3628800

思路

典型的大數階乘問題,核心思路就是用數組存儲結果中的每一個數字,主要是進位三部曲。注意個位在最後,最高位在最前面。

代碼

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

int main()
{
	int n = 0;
	cin >> n;
	vector<int> v(3000, 0);
	v[0] = 1;
	int dight = 1;//代表當前數字位數,第一次是1位數
	int temp, num = 0;
	for (int i = 2; i <= n; i++)
	{
		num = 0;//注意每次要將num置0
		for (int j = 0; j < dight; j++)
		{
		//進位三部曲
			temp = v[j] * i + num;
			v[j] = temp % 10;//每一次數字的個位數
			num = temp / 10;
		}
		while (num)//掃尾工作:代表不止dight位數,需要將最後的最高位進行存儲
		{
			v[dight] = num % 10;
			num /= 10;
			dight++;
		}
	}
	//從前往後輸出
	for (int i = dight - 1; i >= 0; i--)
	{
		cout << v[i];
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章