寒假程序設計訓練1:Vijos基礎訓練——基本程序設計與字符串簡單處理(2021/01/01)

2021寒假程序設計訓練Vijos(2021-01-01)

T1:珠心算測驗

在這裏插入圖片描述
在這裏插入圖片描述

T1個人參考程序:

#include <iostream>
using namespace std;

const int maxn = 105;
const int maxv = 1e4 + 5;
int n, a[maxn], ans;
bool isVis[maxv];

int main()
{
	cin >> n;
	for(int i = 0;i < n;++i)
	{
		cin >> a[i];
		isVis[a[i]] = true;
	}
	for(int i = 0;i < n;++i)
	{
		for(int j = i + 1;j < n;++j)
		{
			int addVal = a[i] + a[j];
			if(addVal >= maxv)
			{
				continue;
			}
			isVis[addVal] = false;
		}
	}
	for(int i = 0;i < n;++i)
	{
		if(!isVis[a[i]])
		{
			ans++;
		}
	}
	cout << ans << endl;
	return 0;
}

T1:易錯點分析

須要注意的是,題目問的是:「有多少個數,剛好等於集合中另外兩個(不一樣的)數之和?」因此重點是知足條件的數的個數,也就是說:1 + 4 = 5 和 2 + 3 = 5 實際上是同樣的!這是一個坑點,如何優雅的編程解決它呢?咱們只須要對全部的兩個不一樣數字的和標記成false,而後去n個數裏找,有多少個數被標記成false了便可!固然,初始化的時候要所有標記成true。ios

T2:乒乓球

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

T2:個人參考程序

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

struct Contest
{
	int win, lose;
};

int main()
{
	vector<Contest> C_11, C_21;
	int w_11 = 0, l_11 = 0;
	int w_21 = 0, l_21 = 0;
	char ch;
	while((ch = getchar()) != 'E')
	{
		if(ch != 'W' && ch != 'L')
			continue;
		if(ch == 'W')
		{
			w_11++;
			w_21++;
		}
		else if(ch == 'L')
		{
			l_11++;
			l_21++;
		}
		if((w_11 >= 11 || l_11 >= 11) && abs(w_11 - l_11) >= 2)
		{
			Contest c;
			c.win = w_11, c.lose = l_11;
			C_11.push_back(c);
			w_11 = l_11 = 0;
		}
		if((w_21 >= 21 || l_21 >= 21) && abs(w_21 - l_21) >= 2)
		{
			Contest c;
			c.win = w_21, c.lose = l_21;
			C_21.push_back(c);
			w_21 = l_21 = 0;
		}
	}
	Contest c_11, c_21;
	if(w_11 >= 0 || l_21 >= 0)
	{
		c_11.win = w_11;
		c_11.lose = l_11;
		C_11.push_back(c_11);
	}
	if(w_21 >= 0 || l_21 >= 0)
	{
		c_21.win = w_21;
		c_21.lose = l_21;
		C_21.push_back(c_21);
	}
	for(int i = 0;i < (int)C_11.size();++i)
	{
		cout << C_11[i].win << ':' << C_11[i].lose << endl;
	}
	for(int i = 0;i < (int)C_21.size();++i)
	{
		cout << endl << C_21[i].win << ':' << C_21[i].lose;
	}
	return 0;
}

T2:易錯點分析

注意審題,若是某一局沒有開打,就是 0:0,因此若是一局剛剛結束立馬輸入了字符 ‘E’,或者是一開始就輸入了一個 ‘E’,則比分就是 0:0,因此須要注意這些!而後不必定每局都是打完了才計分,要注意計分的時候有沒打完的殘局哦!git

T3:字符串還原

在這裏插入圖片描述
在這裏插入圖片描述

T3:個人參考程序:

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

bool isValid(string str, int p1, int p2, int n, int k, string s[])
{
	string cur_1, cur_2;
	cur_1 = string(str);
	cur_2 = string(str);
	for(int i = 0;i < n;++i)
		cur_1[i] = ((int)cur_1[i] - 97 - k + 26) % 26 + 'a';
	for(int i = 0;i < n;++i)
		cur_2[i] = ((int)cur_2[i] - 97 + k) % 26 + 'a';
	if(cur_1 == s[p1] && cur_2 == s[p2])
		return true;
	if(cur_1 == s[p2] && cur_2 == s[p1])
		return true;
	return false;
}

int main()
{
	int n, p1, p2, flag = 0;
	string s[3], ans, str = "abcd";
	cin >> n;
	cin >> s[0] >> s[1] >> s[2];
	for(int i = 0;i < 3;++i)
	{
		ans = string(s[i]);
		reverse(ans.begin(), ans.end());
		if(i == 0)	
			p1 = 1, p2 = 2;
		else if(i == 1)
			p1 = 0, p2 = 2;
		else
			p1 = 0, p2 = 1;
		for(int k = 0;k < 26;++k)
		{
			if(isValid(ans, p1, p2, n, k, s))
			{
				flag = 1;
				break;
			}
		}
		if(flag)
		{
			break;
		}
	}
	cout << ans << endl;
	return 0;
}

T3:易錯點分析

這個題實際上是很簡單的,可是我作了挺久,由於我手太生疏了,好久不作題不敲代碼了(因此纔有了這波寒假程序設計強化訓練嘛~),可是仍是想說兩點:算法

一、這個k沒肯定,那就是須要遍歷查找的,這個不能糊塗
二、字符串循環移位的時候,若是是對 26 取模,必定要先減 97 讓它映射到 [0, 26) 的區間上去
三、哎,過久不作題了,作點基礎題你們見諒……編程

T4:ISBN號碼

在這裏插入圖片描述
在這裏插入圖片描述

T4:個人參考程序

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

int main()
{
	string isbnCode;
	cin >> isbnCode;
	int base = 1, len = (int)isbnCode.length(), cnt = 0;
	for(int i = 0;i < len - 1;++i)
	{
		if(isdigit(isbnCode[i]))
		{
			cnt += base * (isbnCode[i] - '0');
			base++;
		}
	}
	cnt %= 11;
	char sign = cnt == 10 ? 'X' : cnt + '0';
	if(isbnCode[len - 1] != sign)
	{
		isbnCode[len - 1] = sign;
		cout << isbnCode << endl;
	}
	else
	{
		cout << "Right" << endl;
	}
	return 0;
}

T4:總結與分析

這個題是大一的時候作過的題目,時間久遠,拿來練練手。好在只作了5分鐘,否則我該切腹自盡了……這題我寫的自認算是比較簡潔啦,沒什麼易錯點,照着模擬便可。數組

T5:笨小猴

在這裏插入圖片描述

在這裏插入圖片描述

T5:個人參考程序

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

const int inf = 0x3f3f3f3f;

bool isPrime(int n)
{
	if(n < 2)
		return false;
	for(int i = 2;i * i <= n;++i)
	{
		if(n % i == 0)
		{
			return false;
		}
	}
	return true;
}

int main()
{
	string str;
	cin >> str;
	int isVis[26], maxn = 0, minn = inf, len = str.length();
	for(int i = 0;i < 26;++i)
	{
		isVis[i] = 0;
	}
	for(int i = 0;i < len;++i)
	{
		int cur = str[i] - 'a';
		isVis[cur]++;
	}
	for(int i = 0;i < 26;++i)
	{
		if(!isVis[i])
			continue;
		if(isVis[i] > maxn)
			maxn = isVis[i];
		if(isVis[i] < minn)
			minn = isVis[i];
	}
	if(isPrime(maxn - minn))
	{
		cout << "Lucky Word" << endl << maxn - minn << endl;
	}
	else
	{
		cout << "No Answer" << endl << 0 << endl;
	}
	return 0;
}

T6:赦免戰俘

在這裏插入圖片描述

在這裏插入圖片描述

T6:個人參考程序

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

const int maxn = 1 << 11;
int n, a[maxn][maxn], l;

void dfs(int r, int c, int len)
{
	if(len <= 0)
		return ;
	for(int i = r;i < r + len;++i)
		for(int j = c;j < c + len;++j)
			a[i][j] = 0;
	dfs(r, c + len, len >> 1);
	dfs(r + len, c, len >> 1);
	dfs(r + len, c + len, len >> 1);
}

int main()
{
	cin >> n;
	l = 1 << n;
	for(int i = 0;i < l;++i)
		for(int j = 0;j < l;++j)
			a[i][j] = 1;
	dfs(0, 0, l >> 1);
	for(int i = 0;i < l;++i)
	{
		for(int j = 0;j < l;++j)
			cout << a[i][j] << ' ';
		cout << endl;
	}
	return 0;
}

T6:算法設計與分析

這題很明顯是個遞歸,每次都是讓左上角赦免(全爲0),既然是遞歸,咱們三步走分析:markdown

一、遞歸出口:
當可以赦免的範圍爲0,也就是左上角正方形邊長爲0的時候,已經不須要赦免了,由於已經沒有人能夠被赦免了!因此此時當時遞歸的出口,也就是遞歸基。app

二、遞歸函數:
每次遍歷左上角,讓數組值變爲0,而後得到右上、右下、左下四個方位的起點,以dfs(起點,長度)爲遞歸函數,每次完成當前赦免任務後進行上述三次遞歸便可!ide

三、遞納入口:
咱們設數組從0開始,那麼入口就是最開始的大正方形的起點,也就是(0, 0),而後赦免的範圍是整個正方形邊長的一半,詳情見程序。函數

T7:幫貢排序

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

T7:個人參考程序

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

const int maxn = 120;

struct Member
{
	string name;
	string work;
	int contribute;
	int rank;
	int mapper_work;
	int id;
}members[maxn];

bool cmp1(Member m1, Member m2)
{
	if(m1.contribute != m2.contribute)
		return m1.contribute > m2.contribute;
	return m1.id < m2.id;
}

bool cmp2(Member m1, Member m2)
{
	if(m1.mapper_work != m2.mapper_work)
		return m1.mapper_work < m2.mapper_work;
	else if(m1.rank != m2.rank)
		return m1.rank > m2.rank;
	else
		return m1.id < m2.id;
}

int main()
{
	map<string, int> mp;
	mp["BangZhu"] = 0, mp["FuBangZhu"] = 1, mp["HuFa"] = 2;
	mp["ZhangLao"] = 3, mp["TangZhu"] = 4, mp["JingYing"] = 5, mp["BangZhong"] = 6;
	int n, r3 = 2, r4 = 4, r5 = 7, r6 = 25;
	cin >> n;
	for(int i = 0;i < n;++i)
	{
		cin >> members[i].name >> members[i].work >> members[i].contribute >> members[i].rank;
		members[i].mapper_work = mp[members[i].work];
		members[i].id = i + 1;
	}
	sort(members + 3, members + n, cmp1);
	for(int i = 3;i < n;++i)
	{
		if(r3 > 0)
		{
			members[i].work = "HuFa";
			r3--;
		}
		else if(r4 > 0)
		{
			members[i].work = "ZhangLao";
			r4--;
		}
		else if(r5 > 0)
		{
			members[i].work = "TangZhu";
			r5--;
		}
		else if(r6 > 0)
		{
			members[i].work = "JingYing";
			r6--;
		}
		else
			members[i].work = "BangZhong";
		members[i].mapper_work = mp[members[i].work];
	}
	sort(members, members + n, cmp2);
	for(int i = 0;i < n;++i)
	{
		cout << members[i].name << ' ' << members[i].work << ' ' << members[i].rank << endl;
	}
	return 0;
}

T7:算法分析與設計

這題標準的模擬,能夠用來訓練天梯賽的L2的一道題(今年那題得分率很低的)。atom

關鍵點:
一、幫主與副幫主不參與排序
二、原來的幫派名單是按照 「職位和等級排序」的,因此最開始三我的確定是「幫主」、「副幫主」
三、首先你須要根據幫貢排序,給每一個人分配新的職位和等級
四、而後再次排序,此次就按照樂斗的:先是職位,再是等級去排序,若是都不知足,通常默認是按照輸入順序排序

總結與反思

今天是程序設計訓練2021年寒假的第一天,是我本身以爲個人程序設計能力在這半年甚至是一年的時間裏發生了很大的退步(比賽成績不理想,作題思惟和手速都慢了),因此但願讓本身得到更高的程序設計與算法設計能力。在此但願鼓舞你們一塊兒參訓,純屬我的組織,難度逐步提高(近一年不專項訓練了,因此難度慢慢來!)。

感謝你們閱讀!

相關文章
相關標籤/搜索