第一题:报数
【题目】:
甲乙丙丁决定玩一个报数的游戏来打发时间。游戏规则为四个人从1开始轮流进行报数,但如果需要报出的数是7的倍数或含有数字7则直接跳过。
此外大家约定,在总共报出了n个数后(不计入被跳过的数)游戏结束。现在需要你来帮忙统计,游戏过程中每个人各自跳过了几次。
【输入】:
从标准输入读入数据。
输入仅一行,包含一个正整数n,表示报出了多少个数后游戏结束。
【输出】:
输出到标准输出。
输出共四行,每行一个整数,依次表示甲乙丙丁四人在游戏过程中跳过的次数。
思路:水题没什么好说的,代码如下
#include<iostream>
using namespace std;
int main()
{
int n;
int gamer[10];
int number;
int count;
while (cin >> n)
{
count=gamer[1] = gamer[2] = gamer[3] = gamer[0]=0;
for (int i = 1; count!=n; i++)
{
if (i % 7 == 0)
{
gamer[i % 4]++;
continue;
}
else
{
number = i;
while (number)
{
if (number % 10 == 7)
{
gamer[i % 4]++;
count--;
break;
}
else number = number / 10;
}
}
count++;
}
//4取余是0,故丁的位置在gamer[0]而不是gamer[4]
cout << gamer[1] << endl << gamer[2] << endl << gamer[3] << endl << gamer[0] << endl;
}
}
第二题: 回收站选址
【题目】:
开学了,可是校园里堆积了不少垃圾杂物。
热心的同学们纷纷自发前来清理,为学校注入正能量~
通过无人机航拍我们已经知晓了n处尚待清理的垃圾位置,其中第i(1<=i<=n)处的坐标为(x,y),保证所有的坐标均为整数。
我们希望在垃圾集中的地方建立些回收站。具体来说,对于一个位置(x, y)是否适合建立回收站,我们主要考虑以下几点:
(x, y)必须是整数坐标,且该处存在垃圾:上下左右四个邻居位置,即(x, y+1),(x, y-1),(x+1, y)和(x-1, y)处,必须全部存在垃圾:进一步地,我们会对满足上述两个条件的选址进行评分,分数为不大于4的自然数,表示在(x±1,y±1)四个对角位置中有几处存在垃圾。
现在,请你统计一下每种得分的选址个数。
【输入】:
从标准输入读入数据。输入总共有n+1行。
第1行包含一个正整数n,表示已查明的垃圾点个数。
第1+i行(1<=i<=n)包含由一个空格分隔的两个整数xi和yi,表示第i处垃圾的坐标。
保证输入的n个坐标互不相同。
【输出】:
输出到标准输出。
输出共五行,每行一个整数,依次表示得分为0、1、2、3和4的回收站选址个数。
思路:
1.一般做题要么是用空间换时间要么是时间换空间,如果本体使用二维数组模拟坐标,测试用例是有用10000以上的坐标作为测试数据的,如果使用二维数组模拟坐标就说明最起码得有index[10000][10000],这显然不现实。
2.所以只能用时间换空间,大力出奇迹就完事了。直接用两重循环,依次比较一个点上下左右的坐标值在数组中有无对应,如果有再判断对角线上的。时间复杂度为:o(n^2)。
代码如下:
#pragma warning(disable:4996)
#include<iostream>
using namespace std;
int main()
{
int n;
int dp;
int input[500];
int member[20];
int i,j;
int flag;
while (cin >> n)
{
memset(member, 0, sizeof(member));
for (i = 0; i < 2 * n; i = i + 2)
cin >> input[i] >> input[i + 1];
for (i = 0, flag = 0, dp = 0; i < 2 * n; i = i + 2,flag=0,dp=0)
{
for (j = 0;j < 2 * n; j = j + 2)
{
if ((input[i] + 1 == input[j] && input[i + 1] == input[j + 1]) ||
(input[i] == input[j] && input[i + 1] + 1 == input[j + 1]) ||
(input[i] - 1 == input[j] && input[i + 1] == input[j + 1]) ||
(input[i] == input[j] && input[i + 1] - 1 == input[j + 1])
)flag++;
}
if (flag == 4)
{
for (j = 0; j < 2 * n; j = j + 2)
{
if ((input[i] + 1 == input[j] && input[i + 1] + 1 == input[j + 1]) ||
(input[i] + 1 == input[j] && input[i + 1] - 1 == input[j + 1]) ||
(input[i] - 1 == input[j] && input[i + 1] + 1 == input[j + 1]) ||
(input[i] - 1 == input[j] && input[i + 1] - 1 == input[j + 1])
)dp++;
}
member[dp]++;
}
}
cout << member[0] << endl << member[1] << endl << member[2] << endl << member[3] << endl << member[4] << endl;
}
}
第三题:化学方程式(没做出)
【题目】:
化学方程式,也称为化学反应方程式,是用化学式表示化学反应的式子。给出一组化学方程式,请你编写程序判断每个方程式是否配平(也就是方程式中等号左右两边的元素种类和对应的原子个数是否相同)。
本题给出的化学方程式由大小写字母、数字和符号(包括等号=、加号+、左圆括号和右圆括号)组成,不会出现其他字符(包括空白字符,如空格、制表符等),化学方程式的格式与化学课本中的形式基本相同(化学式中表示元素原子个数的下标用正常文本,如H2O写成H2O),用自然语言描述如下:
化学方程式由左右两个表达式组成,中间用一个等号三连接,如2H2+O2=2H2O;
表达式由若干部分组成,每部分由系数和化学式构成,部分之间用加号+连接,如2H2+O2、2H2O;
系数是整数或空串,如为空串表示系数为1;
整数由一个或多个数字构成;
化学式由若干部分组成,每部分由项和系数构成,部分之间直接连接,如H2O、CO2、Ca(OH)2、Ba3(PO4)2;
项是元素或用左右圆括号括起来的化学式,如H、Ca、(OH)、(P04);
元素可以是一个大写字母,也可以是一个大写字母跟着一个小写字母,如H、O、Ca。
【输入】:
从标准输入读入数据。
输入的第一行包含一个正整数n,表示输入的化学方程式个数。
接下来n行,每行是一个符合定义的化学方程式。
【输出】:
输出到标准输出。
输出共n行,每行是一个大写字母Y或N,回答输入中相应的化学方程式是否配平。
思路:
1、一个元素必然由一个大写字母开头如C,Cl,所以将大写字母开头的视为一个元素,如果开头的是数字,那么后面全体元素个数都要乘以这个数字,如果数字在元素后面出现,那么这个数字的前一个元素就要乘以这个数字。
做不出来的地方:括号嵌套。有些案例嵌套非常多的括号,如果要解决这个问题要加入很多判断,我又想不到特别精简的做法。最近忙着学习安卓开发,无瑕再画大量时间去刚一道码量巨多的题。
#pragma warning(disable:4996)
#include<iostream>
#include<sstream>
#include <string>
#include <vector>
#include<algorithm>
#include<map>
#include<ctype.h>
#include <math.h>
using namespace std;
bool judge(map<char, int> &left, map<char, int> &right) { //判断两个map是否相同
if (left.size() != right.size()) return false;
for (map<char, int>::iterator it = left.begin(); it != left.end(); ++it) {
if (right[it->first] != it->second) return false;
}
return true;
}
int get_string_int(string s, int pos)
{
int number;
int j;
stringstream stream;
string num;
for (j = pos + 1; j < s.length(); j++)
if (!isdigit(s[j]))
break;
num = s.substr(pos, j);//substr不包括j
stream<<num;
stream >> number;
return number;
}
map<char, int> count_alphabet(string equation_part[50])
{
int i,j,k,now_index,base,end_base;
map<char, int> hash;
for (i = 0; i < equation_part->length(); i++)
{
if (isdigit(equation_part[i][0]))//如果某个开头是数字,就要确认他的base
{
base = get_string_int(equation_part[i], 0);
for (j = log10(base) + 1, now_index= log10(base); j < equation_part[i].length(); j++)//计算字符
{
if (isdigit(equation_part[i][j]))
{
//cout << "left_equation_part[i][j])=" << left_equation_part[i][j]<< endl;
end_base = get_string_int(equation_part[i], j);//这一行出异常
//cout << "base=" << base << " " << "end_base=" << end_base << endl;
for (k = now_index; k < j; k++)//回到第一个字符出现的位置
{
hash[equation_part[i][k]] += 1 * base*end_base;
}
//更新下一个字符起始位置,循环结束会++
j = now_index = j + log10(end_base);
}
else if (j == equation_part[i].length()-1)
{
end_base = 1;//这一行出异常
//cout << "base=" << base << " " << "end_base=" << end_base << endl;
for (k = now_index+1; k <= j; k++)//回到第一个字符出现的位置
{
hash[equation_part[i][k]] += 1 * base*end_base;
}
//更新下一个字符起始位置,循环结束会++,所以在此减1
j = now_index = j + log10(end_base);
}
}
}
else
{
base = 1;
for (j = now_index = 0; j < equation_part[i].length(); j++)//计算字符
{
if (isdigit(equation_part[i][j]))
{
end_base = get_string_int(equation_part[i], j);//这一行出异常
for (k = now_index; k < j; k++)//回到第一个字符出现的位置
{
hash[equation_part[i][k]] += 1 * base*end_base;
}
j = now_index = j + log10(end_base);
}
else if (j == equation_part[i].length() - 1)
{
end_base = 1;//这一行出异常
//cout << "base=" << base << " " << "end_base=" << end_base << endl;
for (k = now_index + 1; k <= j; k++)//回到第一个字符出现的位置
{
hash[equation_part[i][k]] += 1 * base*end_base;
}
//更新下一个字符起始位置,循环结束会++,所以在此减1
j = now_index = j + log10(end_base);
}
}
}
}
return hash;
}
int main()
{
map<char, int> left_map;
map<char, int> right_map;
int n,m;
int i, j, k;
int base,end_base;
int index,pos,now_index;
string total_equation;
string left_equation;
string right_equation;
string left_equation_part[50];
string right_equation_part[50];
cin >> n;
while (n)
{
pos=m=index = 0;
cin >> total_equation;
left_equation = total_equation.substr(0, total_equation.find("="));
right_equation = total_equation.substr(total_equation.find("=")+1,total_equation.length());
//切割等号左边
while (left_equation.find("+",pos)!=string::npos)
{
index = left_equation.find("+",pos);
left_equation_part[m++] = left_equation.substr(pos,index);
pos = index+1;
}
left_equation_part[m++] = left_equation.substr(pos, left_equation.length());
//切割等号右边
pos = m = index = 0;
while (right_equation.find("+", pos) != string::npos)
{
index = right_equation.find("+", pos);
right_equation_part[m++] = right_equation.substr(pos, index);
pos = index + 1;
}
right_equation_part[m++] = right_equation.substr(pos, right_equation.length());
cout << left_equation << endl<<"?"<< right_equation_part[0] <<endl;
//下面开始处理左边的
//cout << "下面开始处理左边的" << endl;
left_map=count_alphabet(left_equation_part);
//下面开始处理右边的
//cout << "下面开始处理右边的" << endl;
right_map=count_alphabet(right_equation_part);
if (judge(left_map, right_map)) cout << "Y" << endl;
else cout << "N" << endl;
}
}