ACM专题---做题目
简介
ACM
纯写题,写思路,写代码
题目
A+B问题I
思路: 不管是a还是b,反正是两变量,而且你的输入不能断,输入一对a、b,给出和的结果;那就是定义两变量,用一个循环,搞定
example
#include <iostream>
using namespace std;
int main()
{
int a, b;
while (cin >> a >> b)
cout << a + b << endl;
return 0;
}
A+B问题II
思路:与上方问题保持一致,但它给多了一个N,其实就是一个输入N的循环
example
#include <iostream>
int main()
{
int N;
int a, b;
while (std::cin >> N)
{
while (N--)
{
std::cin >> a >> b;
std::cout << a + b << std::endl;
}
}
return 0;
}
A+B问题III
思路:与上面的大循环一样的结构,增加了标志输入结束,其实就是一个判断条件,不需要计算,那中断这个循环就不会计算了
example
#include <iostream>
int main()
{
int a, b;
while (std::cin >> a >> b)
{
if (0 == a && 0 == b)
break;
std::cout << a + b << std::endl;
}
return 0;
}
A+B问题IV
思路:与上面的大循环一样的结构,但是循环的条件变了,变成输入N
example
#include <iostream>
int main()
{
int N;
int a, sum = 0;
while (std::cin >> N)
{
if (0 == N)
break;
while (N--)
{
std::cin >> a;
sum += a;
}
std::cout << sum << std::endl;
sum = 0;
}
return 0;
}
A+B问题VII
思路:很简单,就是在I的基础上加多一个换行符
example
#include <iostream>
int main()
{
int a, b;
while (std::cin >> a >> b)
{
std::cout << a + b << std::endl;
std::cout << std::endl;
}
return 0;
}
A+B问题VIII
思路:两层循环一个是总的输出M,然后是单个输出的数量N
example
#include <iostream>
int main()
{
int M, N;
int a, sum = 0;
while (std::cin >> M)
{
while (M--)
{
std::cin >> N;
while (N--)
{
std::cin >> a;
sum += a;
}
std::cout << sum << std::endl;
sum = 0;
if (0 != M)
std::cout << std::endl;
}
}
return 0;
}
平均绩点
思路:假设输入是一个字符串,我们只需要提取字符串里的字母就够了,然后记录有几个字母,记一下字母所代表数字的总和
example
#include <iostream>
#include <string>
#include<sstream>
#include <stdio.h>
int main() {
int num = 0;//记录有几个字母
double sum = 0.0;//总和
std::string str;//输入
bool flag = false;//判断是否输出Unknown
while (getline(std::cin, str)) { //getline函数的使用
for (int i = 0; i < str.size(); i++) {
switch (str[i]) { //字符串[]重载
case 'A':
{
num++;
sum += 4;
break;
}
case 'B':
{
num++;
sum += 3;
break;
}
case 'C':
{
num++;
sum += 2;
break;
}
case 'D':
{
num++;
sum += 1;
break;
}
case 'F':
{
num++;
sum += 0;
break;
}
case ' ':
break;
default:
flag = true;
break;
}
}
if (flag) {
std::cout << "Unknown" << std::endl;
num = 0;
sum = 0;
flag = false;
}
else {
printf("%0.2lf\n", sum / num);
num = 0;
sum = 0;
}
}
return 0;
}
搭积木
思路:最少的移步,我们可以看到这题就是一个找规律的题目
1. 举例子,也就是递推法
2. 找到相似的公式一步一步逼近你要的结果---逼近法
example
//我用的是第一种方法
#include <iostream>
#include <vector>
int MoveLeastStep(int num) //找到最少移动步数
{
std::vector<int> height; //容器用来接收输入的高
int sum = 0;
for (int i = 0; i < num; i++) {
int a;
std::cin >> a; // 输入
height.push_back(a); //接收
sum += height[i]; //求和
}
int average = sum / num; //求平均
int leaststep = 0;
for (int i = 0; i < num; i++) {
if (height[i] - average > 0) // height[i] - average 这个数如果循环走num次,
//就会为了,其中正负数相抵消,所以你要记录全正的,或者全负的数,就是移动最少的次数
leaststep += height[i] - average;
}
return leaststep;
}
void test1()
{
int num;
while (std::cin >> num)
{
if (0 == num)
break;
int least = MoveLeastStep(num);
std::cout << least << std::endl;
std::cout << std::endl;
}
}
int main()
{
test1();
return 0;
}
奇怪的信
思路:
- 取各个位置上的数,判断是否为偶数
2.求和
example
#include <iostream>
int main(){
int num;
while (std::cin >> num) {
int n = num;
int sum = 0;
while (n) {
if ((n % 10) % 2 == 0)
sum += n % 10;
n /= 10;
}
std::cout << sum << std::endl;
std::cout << " ";
sum = 0;
}
return 0;
}
运营商活动
思路:
- 最开始的钱数就是天数,我们要搞清钱数跟天数的关系
2.后面送的钱,我们单独算
example
#include <iostream>
int main() {
int M, K;
int re = 0;
int sum = 0;
while (true) {
std::cin >> M >> K;
if (M == 0 && K == 0)
break;
//最开始的钱
sum += M;
int song_num = 0;
//最开始的钱通过K的转化,又可以多song_num天
//19 / 3 = 6···1
//7 / 3 = 2···1
//3 / 3 = 1···0
//19+6+2+1 = 29
while (M >= K) {
song_num += M / K;
re = M % K;
M = M / K + re;
}
//std::cout << song_num << std::endl;
sum += song_num;
std::cout << sum << std::endl;
sum = 0;
re = 0;
}
}
共同祖先
思路:用两个vector空间去存输入的数字,然后根据链式求和他们各有的数字,数字多的就是辈分小,数字少的就是备份大
eg:1356,246,这就是链式,然后第一个有4个数字,第二个有3个数字,所以输出为older
example
#include <iostream>
#include <vector>
int main() {
int son, father;
int sum_1 = 2, sum_2 = 2;
int N;
std::vector<int> v1, v2;
int stand = 0;
while (std::cin >> N) {
int m = N;
while(N--) {
std::cin >> son >> father;
v1.push_back(son);
v2.push_back(father);
}
for(int i = 0; i < m; i++) {
if (v1[i] == 1) {
stand = i;
break;
}
}
for(int i = 0; i < m; i++) {
if (v2[stand] == v1[i]) {
stand = i;
sum_1++;
}
}
for(int i = 0; i < m; i++) {
if (v1[i] == 2) {
stand = i;
break;
}
}
for(int i = 0; i < m; i++) {
if (v2[stand] == v1[i]) {
stand = i;
sum_2++;
}
}
if (sum_1 == sum_2) std::cout << "You are my brother" << std::endl;
else if (sum_1 > sum_2) std::cout << "You are my elder" << std::endl;
else if (sum_1 < sum_2) std::cout << "You are my younger" << std::endl;
// std::cout << "1:" << sum_1 << std::endl;
// std::cout << "2:" << sum_2 << std::endl;
sum_1 = 2;
sum_2 = 2;
v1.clear();
v2.clear();
}
return 0;
}
打印数字图形
思路:我们把这个图形打印分成四部分,即四个象限,按示例的中心就是123454321,我们每次打印就分成了四小步,具体操作看代码吧
example
#include <iostream>
int main()
{
int a;
while(std::cin >> a) {
for (int i = 0; i < a; i++) {//打印上n行
//1. 打空格
for (int ii = a - i - 1; ii > 0; ii--) {
std::cout << " ";
}
//2. 打左边数字
for (int iii = 1; iii <= (i + 1); iii++) {
std::cout << iii;
}
//3. 打右边数字
for (int iiii = i; iiii > 0; iiii--) {
std::cout << iiii;
}
std::cout << std::endl;
}
for (int i = 0; i < a - 1; i++) { //打印下n行
//1. 打空格
for (int ii = 0; ii < (i + 1); ii++) {
std::cout << " ";
}
//2. 打左边数字
for (int iii = 1; iii < a - i; iii++) {
std::cout << iii;
}
//3. 打右边数字
for (int iiii = a - i - 2; iiii > 0; iiii--) {
std::cout << iiii;
}
std::cout << std::endl;
}
}
}
镂空三角形
思路:我们把这个图形打印分成四部分,(空格+字母)这个打印格式可以当成同一种,具体操作看代码吧
- 左边空格+字母
- 左边空格
- 右边空格+字母
- 最后一行
example
#include <iostream>
int main() {
char ch;
int a;
while (std::cin >> ch >> a) {
if ('@' == ch) break;
for (int i = 0; i < a; i++) {//i = 0~6变化
//1. 在左边打印空格,最后空格后打一个ch
for (int ii = a - i - 1; ii > 0; ii--) {
std::cout << " ";
if (ii == 1) {
std::cout << ch;
}
}
//2. 在左边打印剩下的空格
if (i < a - 1) {
for (int iii = 0; iii < i; iii++) {
std::cout << " ";
}
//3. 在右边打印空格,最后一个空格打一个ch
for (int iiii = 0; iiii < i - 1; iiii++) {
std::cout << " ";
if (iiii == i - 2) {
std::cout << ch;
}
}
if (i == 1) { // 特殊情况
std::cout << ch;
}
}
//4. 最后一行全打印ch
if (i == a - 1) {
for (int i = 0; i < 2*a - 1; i++) {
std::cout << ch;
}
}
std::cout << std::endl;
}
std::cout << std::endl;
}
return 0;
}
句子缩写
思路:这题我们可以看出来,靠这题已经不是思路的问题了,是考你的基本功扎不扎实
- 输入怎么接收?
- 处理过程就是空格+字母然后记录
- 完成字母的转化
注意:
- c++字符串,结尾不一定是'\0',所以判断结束条件->
index < str.length()
; - str.at()访问string类比[]访问string类的好处是,at方法会检查越界;
- str.clear()只会清除str[0]元素的内容,并不会减小str的容量,而且后面的str[1]、str[2]不会做清除操作;
example
#include <iostream>
#include <string>
#include <limits>
#include <stdio.h>
int main() {
//1
//ad dfa fga
//在1后面有一个'\n'我们需要先清除
//读取数据
// int number;
// std::string line;
// // Read an integer
// std::cin >> number;
// // Remove the newline character from the input buffer
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// // Read a line of text
// std::getline(std::cin, line);
// std::cout << line;
//读取数据
/*
int n;
std::cin >> n;
std::string receiveStr;
char ch;
while((ch = getchar()) != '\n') ;
getline(std::cin, receiveStr);
std::cout << receiveStr;
*/
int n;
std::cin >> n;
char ch;
while((ch = getchar()) != '\n');//清除最后一个'\n'
std::string saveStr = "";//最后的结果
std::string receiveStr;//接收字符
while(n--) {
getline(std::cin, receiveStr);
int pointer = 0;
int receiveStrLen = receiveStr.length();
//std::cout << "receiveStrLen" << receiveStrLen << std::endl;
while (pointer < receiveStrLen) {
while (pointer < receiveStrLen && receiveStr.at(pointer) == ' ') pointer++;
saveStr += receiveStr.at(pointer);
pointer++;
while (pointer < receiveStrLen && receiveStr.at(pointer) != ' ') pointer++;
//std::cout << "pointer" << pointer << std::endl;
}
//std::cout << "pointer" << pointer << std::endl;
int saveStrLen = saveStr.length();
int correctPtr = 0;
while (correctPtr < saveStrLen) {
if (saveStr.at(correctPtr) >= 'a') {
saveStr.at(correctPtr) -= 32;
}
correctPtr++;
}
std::cout << saveStr << std::endl;
saveStr.clear();
receiveStr.clear();
}
return 0;
}