团队天梯赛L1

L1-002 打印沙漏 (20 分)

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:
19 *
输出样例:

*****
 ***
  *
 ***
*****
2
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    char ch;
    cin >> n >> ch;
    if(n==0){
        cout << "0" << endl;
        return 0;
    }
    int need = 1;
    int layer;
    for(int i=2;;i++){
        need += 2*(i*2-1);
        if(need>n){
            need -= 2*(i*2-1);
            i--;
            layer = i;
            break;
        }
    }
    for(int i=layer;i>=1;i--){
        for(int j=0;j<layer-i;j++) cout << " ";
        for(int k=0;k<2*i-1;k++) cout << ch;
        cout << endl;
    }
    for(int i=2;i<=layer;i++){
        for(int j=0;j<layer-i;j++) cout << " ";
        for(int k=0;k<2*i-1;k++) cout << ch;
        cout << endl;
    }
    cout << n-need << endl;
    return 0;
}

L1-003 个位数统计 (15 分)

给定一个 k 位整数N=d ​k−1 ​​ 10 ​k−1 ​​ +⋯+d ​1 ​​ 10 ​1 ​​ +d ​0 ​​ (0≤d ​i ​​ ≤9, i=0,⋯,k−1, d ​k−1 ​​ >0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。

输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。

输出格式:
对 N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。

输入样例:
100311
输出样例:
0:2
1:3
3:1

用map实现

#include<bits/stdc++.h>
using namespace std;
map<int ,int> mp;
int main(){
    string s;
    cin >> s;
    for(int i=0;i<s.length();i++){
        mp[s[i]-'0']++;
    }
    for(map<int,int>::iterator it = mp.begin();it!=mp.end();it++){ //
        printf("%d:%d\n",it->first,it->second);
    }
    return 0;
}

用数组实现

#include <stdio.h>
#include <ctype.h>
#include<iostream>
using namespace std;
int main(){
    int a[10] = {0};
    int n;
    char c;
    while((c = cin.get()) != '\n'){
    	n = c-'0';
    	a[n]++;
	}
    for(int i = 0; i < 10; i++){
        if(a[i] != 0){
            printf("%d:%d\n",i,a[i]);
        }
    }
    return 0;
}

L1-005 考试座位号 (15 分)

每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。

输入格式:
输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 16 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。

考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。

输出格式:
对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。

输入样例:
4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4
输出样例:
3310120150912002 2
3310120150912119 1

C++实现

#include<bits/stdc++.h>
using namespace std;
typedef struct{
    char zkz[20];
    int sj,ks;
}Student;
vector<Student> s;
int main(){
    int n,m;
    scanf("%d",&n);
//     getchar(); //这里不需要
    for(int i=0;i<n;i++){
        Student st;
        scanf("%s %d %d",&st.zkz,&st.sj,&st.ks);
//         getchar();
        s.push_back(st);
    }
    scanf("%d",&m);
//     getchar();
    for(int i=0;i<m;i++){
        int a;
        scanf("%d",&a);
//         getchar();
        for(int j=0;j<s.size();j++){
            if(a == s[j].sj){
                printf("%s %d\n",s[j].zkz,s[j].ks);
            }
        }
    }
    return 0;
}

Python 实现

if __name__ == '__main__':
    n = int(input())
    id1,id3 = [0]*1010,[0]*1010
    while(n > 0):
        li = list(map(str,input().split()))
        i = int(li[1])
        id1[i],id3[i] = li[0],li[2]
        n -= 1
    m = int(input())
    if m != 0:
        d = list(map(int,input().split()))
        for i in d:
            print("{} {}".format(id1[i],id3[i]))
    exit(0)

L1-016 查验身份证 (15 分)

一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2
现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式:
输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

输出格式:
按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed。

输入样例1:
4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X
输出样例1:
12010X198901011234
110108196711301866
37070419881216001X
输入样例2:
2
320124198808240056
110108196711301862
输出样例2:
All passed

#include<bits/stdc++.h>
using namespace std;
int weight[20] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char M[11] = {'1','0','X','9','8','7','6','5','4','3','2'};
int main(){
    int n;
    cin >> n;
    cin.ignore();
    string id;
    int flag=1;
    vector<string> s; 
    for(int i=0;i<n;i++){
        cin >> id;
        cin.ignore();
        int sum=0;
        for(int j=0;j<17;j++){
            sum += weight[j]*(id[j]-'0');
        }
        if(id[17] != M[sum%11]){
            flag = 0;
            s.push_back(id);
        }
    }
    if(flag){
        printf("All passed\n");
    }else{
        for(int i=0;i<s.size();i++){
            cout << s[i] << endl;
        }
    }
    return 0;
}

L1-017 到底有多二 (15 分)

一个整数“犯二的程度”定义为该数字中包含2的个数与其位数的比值。如果这个数是负数,则程度增加0.5倍;如果还是个偶数,则再增加1倍。例如数字-13142223336是个11位数,其中有3个2,并且是负数,也是偶数,则它的犯二程度计算为:3/11×1.5×2×100%,约为81.82%。本题就请你计算一个给定整数到底有多二。

输入格式:
输入第一行给出一个不超过50位的整数N。

输出格式:
在一行中输出N犯二的程度,保留小数点后两位。

输入样例:
-13142223336
输出样例:
81.82%

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin >> s;
    double sum=0;
    int l = s.length();
    for(int i=0;i<l;i++){
        if(s[i]=='2') sum++;
    }
    double res;
    if(s[0]=='-'){
        res = 1.5*sum/(double)(l-1);
    }else{
        res = sum/(double)l;
    }
    if((s[l-1]-'0')%2==0) res *= 2; //理解题意,偶数条件不是包含在负数条件里的
    printf("%0.2f%%\n",res*100);
    return 0;
}

L1-019 谁先倒 (15 分)

题目说明:
划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。

下面给出甲、乙两人的酒量(最多能喝多少杯不倒)和划拳记录,请你判断两个人谁先倒。

输入格式:
输入第一行先后给出甲、乙两人的酒量(不超过100的非负整数),以空格分隔。下一行给出一个正整数N(≤100),随后N行,每行给出一轮划拳的记录,格式为:

甲喊 甲划 乙喊 乙划
其中喊是喊出的数字,划是划出的数字,均为不超过100的正整数(两只手一起划)。

输出格式:
在第一行中输出先倒下的那个人:A代表甲,B代表乙。第二行中输出没倒的那个人喝了多少杯。题目保证有一个人倒下。注意程序处理到有人倒下就终止,后面的数据不必处理。

输入样例:
1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16
输出样例:
A
1

#include<bits/stdc++.h>
using namespace std;

int a,b;
int r; //多少轮
int main(){
    scanf("%d %d",&a,&b);
    scanf("%d",&r);
    int jh = 0,yh = 0;
    for(int i=0; i<r; i++){
        
        int j1,j2,y1,y2;
        scanf("%d %d %d %d",&j1,&j2,&y1,&y2);
        if(j1+y1 != j2 && j1+y1 == y2){
            yh++;
        }
        if(j1+y1 == j2 && j1+y1 != y2){
            jh++;
        }
        if(a < jh){			// 这两个判断放在判断jh和yh是否要++之前和之后的效果不一样,还没想明白为什么
            printf("A\n");
            printf("%d\n",yh);
            break;
        }
        if(b < yh){
            printf("B\n");
            printf("%d\n",jh);
            break;
        }						//
    }
    return 0;
}

L1-020 帅到没朋友 (20 分)

当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。

输入格式:
输入第一行给出一个正整数N(≤100),是已知朋友圈的个数;随后N行,每行首先给出一个正整数K(≤1000),为朋友圈中的人数,然后列出一个朋友圈内的所有人——为方便起见,每人对应一个ID号,为5位数字(从00000到99999),ID间以空格分隔;之后给出一个正整数M(≤10000),为待查询的人数;随后一行中列出M个待查询的ID,以空格分隔。

注意:没有朋友的人可以是根本没安装“朋友圈”,也可以是只有自己一个人在朋友圈的人。虽然有个别自恋狂会自己把自己反复加进朋友圈,但题目保证所有K超过1的朋友圈里都至少有2个不同的人。

输出格式:
按输入的顺序输出那些帅到没朋友的人。ID间用1个空格分隔,行的首尾不得有多余空格。如果没有人太帅,则输出No one is handsome。

注意:同一个人可以被查询多次,但只输出一次。

输入样例1:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888
输出样例1:
10000 88888 23333
输入样例2:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111
输出样例2:
No one is handsome

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int k[N] = {0};
int main(){
    int n;
    cin >> n;
    int m,id;
    for(int i=0;i<n;i++){
        cin >> m;
        if(m<=1){
            cin >> id; //虽然要continue,但是该从键盘吸收的数还是要吸收掉
            continue;
        }
        for(int j=0;j<m;j++){
            cin >>id;
            k[id]++;
        }
    }
    cin >>m;
    int flag = 1;
    for(int i=0;i<m;i++){
        cin >> id;
        if(k[id]==0){
            if(flag){
                printf("%05d",id);
            }else{
                printf(" %05d",id);
            }
            flag = 0;
            k[id]++;
        }
    }
    if(flag){
        cout << "No one is handsome";
    }
    cout << endl;
    return 0;
}

L1-025 正整数A+B (15 分)

题的目标很简单,就是求两个正整数A和B的和,其中A和B都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。

输入格式:
输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。

注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。

输出格式:
如果输入的确是两个正整数,则按格式A + B = 和输出。如果某个输入不合要求,则在相应位置输出?,显然此时和也是?。

输入样例1:
123 456
输出样例1:
123 + 456 = 579
输入样例2:
22. 18
输出样例2:
? + 18 = ?
输入样例3:
-100 blabla bla…33
输出样例3:
? + ? = ?

注意:

  1. 当string中有除了数字以外的特殊字符时,直接输出会乱码,所以本题最好不要直接用%s输出
  2. C++中的isdigit()是对单个字符的检查
  3. 在检查输入的字符串的时候就做好判断及类型的转换,最后输出最好一边判断一边输出
  4. 问题规模小,不要嫌麻烦,考试不要在这种题上浪费太多时间!!

C++实现:

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int check(string s){
    int sum = 0;
    for(int i=0;i<s.length();i++){
        if(!isdigit(s[i])){
            return -1;
        }else{
            sum = sum*10+s[i]-'0';
        } 
    }
    if(sum<1 || sum>1000 || s == "") return -1;
    return sum;
}
int main(){
    cin >> s1;
    getchar();
    getline(cin,s2);
    if(check(s1) != -1 &&check(s2) != -1){
        int n = check(s1)+check(s2);
        printf("%d + %d = %d\n",check(s1),check(s2),n);
        return 0;
    }
    if(check(s1) == -1){
        printf("? + ");
    }else{
        printf("%d + ",check(s1));
    }
    if(check(s2) == -1){
        printf("? = ");
    }else{
        printf("%d = ",check(s2));
    }
    printf("?");
    return 0;
}

L1-034 点赞 (20 分)

微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。本题就要求你写个程序,通过统计一个人点赞的纪录,分析这个人的特性。

输入格式:
输入在第一行给出一个正整数N(≤1000),是该用户点赞的博文数量。随后N行,每行给出一篇被其点赞的博文的特性描述,格式为“K F ​1 ​​ ⋯F ​K ​​ ”,其中1≤K≤10,F ​i ​​ (i=1,⋯,K)是特性标签的编号,我们将所有特性标签从1到1000编号。数字间以空格分隔。

输出格式:
统计所有被点赞的博文中最常出现的那个特性标签,在一行中输出它的编号和出现次数,数字间隔1个空格。如果有并列,则输出编号最大的那个。

输入样例:
4
3 889 233 2
5 100 3 233 2 73
4 3 73 889 2
2 233 123
输出样例:
233 3

C++实现

#include<bits/stdc++.h>
using namespace std;
int n;
int k,t;
int a[1010]={0};
int main(){
    cin >> n;
    for(int i=0;i<n;i++){
        cin >> k;
        for(int j=0;j<k;j++){
            cin >> t;
            a[t]++;
        }
    }
    int maxV = *max_element(a,a+1010);
    for(int i=1009;i>=0;i--){
        if(a[i]==maxV){
            printf("%d %d\n",i,maxV);
            return 0;
        }
    }
}

L1-039 古风排版 (20 分)

中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。

输入格式:
输入在第一行给出一个正整数N(<100),是每一列的字符数。第二行给出一个长度不超过1000的非空字符串,以回车结束。

输出格式:
按古风格式排版给定的字符串,每列N个字符(除了最后一列可能不足N个)。

输入样例:
4
This is a test case
输出样例:
asa T
st ih
e tsi
ce s

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    int n;
    cin >> n;
    getchar();  //!!!吸收掉回车
    getline(cin,s);
    int l = s.length();
    int h;
    if(l%n == 0){
        h = l/n;
    }else{
        h = l/n+1;
        for(int i=0;i<h*n-l;i++){
            s += " ";
        }
    }
    
    char a[h][n];
    for(int i=0;i<h;i++){
        for(int j=0;j<n;j++){
            a[i][j] = s[i*n+j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=h-1;j>=0;j--){
            printf("%c",a[j][i]);
        }
        printf("\n");
    }
}

L1-043 阅览室 (20 分)

天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时,管理员输入书号并按下S键,程序开始计时;当读者还书时,管理员输入书号并按下E键,程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号输入时,表示一天工作结束,你的程序应输出当天的读者借书次数和平均阅读时间。

注意:由于线路偶尔会有故障,可能出现不完整的纪录,即只有S没有E,或者只有E没有S的纪录,系统应能自动忽略这种无效纪录。另外,题目保证书号是书的唯一标识,同一本书在任何时间区间内只可能被一位读者借阅。

输入格式:
输入在第一行给出一个正整数N(≤10),随后给出N天的纪录。每天的纪录由若干次借阅操作组成,每次操作占一行,格式为:

书号([1, 1000]内的整数) 键值(S或E) 发生时间(hh:mm,其中hh是[0,23]内的整数,mm是[0, 59]内整数)

每一天的纪录保证按时间递增的顺序给出。

输出格式:
对每天的纪录,在一行中输出当天的读者借书次数和平均阅读时间(以分钟为单位的精确到个位的整数时间)。

输入样例:
3
1 S 08:10
2 S 08:35
1 E 10:00
2 E 13:16
0 S 17:00
0 S 17:00
3 E 08:10
1 S 08:20
2 S 09:00
1 E 09:20
0 E 17:00
输出样例:
2 196
0 0
1 60

注意:

  1. 舍入只考虑小数点后的一位,比如1.5656467846舍入只和1.5这个5有关系,和后面的656467846没有关系。prinf输出浮点数自带四舍五入(但此题需要手动+0.5f)。3舍4入就改成+0.6f(1-0.4),6舍7入就改成+0.3f(1-0.7)
  2. 0既不是正整数,也不是负整数(0是整数)
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    for(int i=0;i<n;i++){
        int num=0;
        double time=0;
        int id,hh,mm;
        char ch;
        int book[1005] = {0};
        bool flag[1005] = {false};
        //     memset(flag,false,sizeof(flag));
        while(true){
            scanf("%d %c %d:%d",&id,&ch,&hh,&mm);
            if(id == 0) break;
            if(ch == 'S'){
                book[id] = hh*60+mm;
                flag[id] = true;
            }else if(ch=='E'){
                if(flag[id]){  //只有E没有S,需要舍弃
                    flag[id] = false;
                    time += hh*60+mm-book[id];
                    num++;
                    book[id] = 0;
                }
            }
        }
        int t ;
        if(num>0){
            t= time/num + 0.5f;
        }else{
            t = 0;
        }
        printf("%d %d\n",num,t);
    }
}

L1-044 稳赢 (15 分)

大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:

现要求你编写一个稳赢不输的程序,根据对方的出招,给出对应的赢招。但是!为了不让对方输得太惨,你需要每隔K次就让一个平局。

输入格式:
输入首先在第一行给出正整数K(≤10),即平局间隔的次数。随后每行给出对方的一次出招:ChuiZi代表“锤子”、JianDao代表“剪刀”、Bu代表“布”。End代表输入结束,这一行不要作为出招处理。

输出格式:
对每一个输入的出招,按要求输出稳赢或平局的招式。每招占一行。

输入样例:
2
ChuiZi
JianDao
Bu
JianDao
Bu
ChuiZi
ChuiZi
End
输出样例:
Bu
ChuiZi
Bu
ChuiZi
JianDao
ChuiZi
Bu

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    cin.ignore();
    int m=0;
    while(true){
        string s;
        cin >> s;
        cin.ignore();
        if(s=="End"){
            break;
        }
        if(m%n==0&&m!=0){
            m=0;	//注意置零
            printf("%s\n",s.c_str());
            continue;
        }
        if(s=="JianDao"){
            printf("ChuiZi\n");
        }else if(s=="ChuiZi"){
            printf("Bu\n");
        }else if(s=="Bu"){
            printf("JianDao\n");
        }
        m++;
    }
}

L1-046 整除光棍 (20 分)

这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。

提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。

输入格式:
输入在一行中给出一个不以5结尾的正奇数x(<1000)。

输出格式:
在一行中输出相应的最小的s和n,其间以1个空格分隔。

输入样例:
31
输出样例:
3584229390681 15

思路:模拟多位1除n的过程,即模拟其除法
Plus:

  1. cout可以直接输出string
  2. int后加+'0'可以转换为string
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    int k=1;
    int l=0;
    string s;
    while(k<n){
        k = k*10+1;
        l++;
    }
    while(k%n!=0){ //模拟除法
        s += k/n+'0';
        k = k%n*10+1;
        l++;
    }
    s += k/n+'0';
    l++;
    cout << s << " " << l << endl;
}
  1. 之前的运行超时的思路(🤦‍
    一直在string s后面加"1",再用转成long long除n,将可以整除的结果
    换为string输出
  2. get到的一些可能有用的东西
    int i = strtoll(str,NULL,base)将string转为long long
    string s = to_string (int val);将long long转为string
  1. C++基础之string与数字(int、long、float、doubel)之间相互转换

  2. strtol&strtoll的参考

L1-048 矩阵A乘以B (15 分)

给定两个矩阵A和B,要求你计算它们的乘积矩阵AB。需要注意的是,只有规模匹配的矩阵才可以相乘。即若A有R
​a
​​ 行、C
​a
​​ 列,B有R
​b
​​ 行、C
​b
​​ 列,则只有C
​a
​​ 与R
​b
​​ 相等时,两个矩阵才能相乘。

输入格式:
输入先后给出两个矩阵A和B。对于每个矩阵,首先在一行中给出其行数R和列数C,随后R行,每行给出C个整数,以1个空格分隔,且行首尾没有多余的空格。输入保证两个矩阵的R和C都是正数,并且所有整数的绝对值不超过100。

输出格式:
若输入的两个矩阵的规模是匹配的,则按照输入的格式输出乘积矩阵AB,否则输出Error: Ca != Rb,其中Ca是A的列数,Rb是B的行数。

输入样例1:
2 3
1 2 3
4 5 6
3 4
7 8 9 0
-1 -2 -3 -4
5 6 7 8
输出样例1:
2 4
20 22 24 16
53 58 63 28
输入样例2:
3 2
38 26
43 -5
0 17
3 2
-11 57
99 68
81 72
输出样例2:
Error: 2 != 3

#include<bits/stdc++.h>
using namespace std;
int main(){
    int ra,ca,rb,cb;
    scanf("%d %d",&ra,&ca);
    int a[ra][ca];
    cin.ignore();
    for(int i=0;i<ra;i++){
        for(int j=0;j<ca;j++){
            cin >> a[i][j];
        }
        cin.ignore();
    }
    scanf("%d %d",&rb,&cb);
    int b[rb][cb];
    cin.ignore();
    for(int i=0;i<rb;i++){
        for(int j=0;j<cb;j++){
            cin >> b[i][j];
        }
        cin.ignore();
    }
    if(ca!=rb){
        printf("Error: %d != %d",ca,rb);
        return 0;
    }
    int res[ra][cb];
    
    printf("%d %d\n",ra,cb);
    for(int i=0;i<ra;i++){
        for(int j=0;j<cb;j++){
            int sum=0;
            for(int k=0;k<ca;k++){
                sum += a[i][k]*b[k][j];
            }
            res[i][j] = sum;
            if(j==cb-1){
                printf("%d",res[i][j]);
            }else{
                printf("%d ",res[i][j]);
            }
            
        }
        printf("\n");
    }
}

L1-049 天梯赛座位分配 (20 分)

天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情。为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i 所学校有 M[i] 支队伍,每队 10 位参赛选手。令每校选手排成一列纵队,第 i+1 队的选手排在第 i 队选手之后。从第 1 所学校开始,各校的第 1 位队员顺次入座,然后是各校的第 2 位队员…… 以此类推。如果最后只剩下 1 所学校的队伍还没有分配座位,则需要安排他们的队员隔位就坐。本题就要求你编写程序,自动为各校生成队员的座位号,从 1 开始编号。

输入格式:
输入在一行中给出参赛的高校数 N (不超过100的正整数);第二行给出 N 个不超过10的正整数,其中第 i 个数对应第 i 所高校的参赛队伍数,数字间以空格分隔。

输出格式:
从第 1 所高校的第 1 支队伍开始,顺次输出队员的座位号。每队占一行,座位号间以 1 个空格分隔,行首尾不得有多余空格。另外,每所高校的第一行按“#X”输出该校的编号X,从 1 开始。

输入样例:
3
3 4 2
输出样例:
#1
1 4 7 10 13 16 19 22 25 28
31 34 37 40 43 46 49 52 55 58
61 63 65 67 69 71 73 75 77 79
#2
2 5 8 11 14 17 20 23 26 29
32 35 38 41 44 47 50 53 56 59
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
#3
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60

看其他大佬的之后写出来de:

#include<bits/stdc++.h>
using namespace std;

struct School{
    int team;
    vector<int> sits;
};

int main(){
    int n;
    cin >> n;
    int res = n;
    int rate = n==1 ? 2:1;
    School s[n];
    for(int i=0;i<n;i++){
        cin >> s[i].team;
    }
    int k = 1;
    while(res){
    	for(int i=0;i<n;i++){
	        if(s[i].sits.size()<s[i].team*10){
	            s[i].sits.push_back(k);
	            if(s[i].sits.size()==s[i].team*10) res--; //如果该校参赛人已经都排了座位
                k += rate;
	            if(res==1){
	                rate=2;
	            }
	            
        	}
    	}
	}
    for(int i=0;i<n;i++){
        printf("#%d\n",i+1);
        for(int j=0;j<s[i].sits.size();j++){
            cout << s[i].sits[j] << (((j+1)%10==0) ? "\n":" ");
        }
    }
    return 0;
}

自己之前的混乱 错误思路

#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int sit[N];
int main(){
    int n;
    cin >> n;
    cin.ignore();
    int a[n],b[n];
    for(int i=0;i<n;i++){
        cin >> a[i];
    }
    for(int i=0;i<n;i++){
        b[i] = a[i]*10;
    }
    int maxI,maxV;
	[maxV,maxI]  = std::max(b[i]);
	cout << maxV << endl;
    for(int i=0;i<n;i++){ //有几个学校
//         for(int j=0;j<=b[i];j++){ //一个学校多少人
//             sit[i+1+j*n]=i+1;
//         }
	
        
    }
    int m=1;
   /*
   for(int j=1;j<=n;j++){
        printf("#%d\n",j);
        for(int i=0;i<N;i++){
            if(sit[i]==j && m%10 !=0){
                printf("%d ",i);
                m++;
            }
            if(sit[i]==j && m%10 ==0){
                printf("%d\n",i);
                m++;
            }
        }
    }
   */ 
    
    return 0;
}

混乱下get到的point:
C++ 中max()与max_element()的区别

L1-050 倒数第N个字符串 (15 分)

给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, …, aaz, aba, abb, …, abz, …, zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。

输入格式:
输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤10
​5
​​ )。

输出格式:
在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。

输入样例:
3 7417
输出样例:
pat

#include<bits/stdc++.h>
using namespace std;
int main(){
    int L,N;
    cin >> L >> N;
    int index[10];
    int res = pow(26,L)-N;
    int i=0;
    while(L--){
        index[i++] = res%26;
        res /= 26;
    }
    char c;
    for(int j=i-1;j>=0;j--)
        cout << (c = index[j]+'a') << ((j==0)?"\n":"");
}
  1. 开始的思路:本来想用next_permutation(a,a+num)做,但是写着写着就没思绪了,方法学习参考了以下博文:
    c++中的全排列
  2. 正解思路:
    L1-050 倒数第N个字符串 (15分)详解

L1-054 福到了 (15 分)

“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @ 或者为空格。而倒过来的汉字所用的字符由裁判指定。

输入格式:
输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @ 或者为空格。

输出格式:
输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le,然后再用输入指定的字符将其输出。

输入样例 1:

$ 9
 @  @@@@@
@@@  @@@ 
 @   @ @ 
@@@  @@@ 
@@@ @@@@@
@@@ @ @ @
@@@ @@@@@
 @  @ @ @
 @  @@@@@

输出样例 1:

$$$$$  $ 
$ $ $  $ 
$$$$$ $$$
$ $ $ $$$
$$$$$ $$$
 $$$  $$$
 $ $   $ 
 $$$  $$$
$$$$$  $ 

输入样例 2:

& 3
@@@
 @ 
@@@

输出样例 2:

bu yong dao le
&&&
 & 
&&&
  1. 思路:定义二维数组,赋值的时候就开两个空间,一个存正序的,一个存倒序的,后面两个直接比较
  2. 注意:读数的时候不管是用cin还是scanf都要吸收掉不要的回车!!
#include<bits/stdc++.h>
using namespace std;
int main(){
    char sign;
    int n;
    cin >> sign >> n;
    cin.ignore(); //一定要把回车吸收掉
    char grid[n][n];
    char grid2[n][n];
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            scanf("%c",&grid[i][j]);
            grid2[n-i-1][n-j-1] = grid[i][j];
        }
        cin.ignore(); //一定要把回车吸收掉
    }
    int flag=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(grid[i][j] != grid2[i][j]){
                flag = 1;
                break;
            }
        }
    }
    if(!flag){
        cout << "bu yong dao le\n";
    }
    for(int i=n-1;i>=0;i--){
        for(int j=n-1;j>=0;j--){
            cout << ((grid[i][j]=='@')?sign:' ');
        }
        cout << endl;
     }

}

L1-056 猜数字 (20 分)

一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。

输入格式:
输入在第一行给出一个正整数N(≤10^​4​​ )。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。

输出格式:
在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。

输入样例:
7
Bob 35
Amy 28
James 98
Alice 11
Jack 45
Smith 33
Chris 62
输出样例:
22 Amy

在C++中,

  1. 如果是int,用INT_MAX表示正无穷,INT_MIN表示负无穷,需要包含头文件limits.h;
  2. 如果是double,用DBL_MAX表示正无穷,DBL_MIN表示负无穷,需要包含文件float.h。
#include<bits/stdc++.h>
using namespace std;
typedef struct{
    char name[10];
    int num;
}Peo;
int main(){
    int n;
    cin >> n;
    Peo p[n];
    cin.ignore();
    int sum=0;
    for(int i=0;i<n;i++){
        scanf("%s %d\n",p[i].name,&p[i].num);
        sum += p[i].num;
    }
    int a = (sum/n)/2;
    int d = INT_MAX;
    int k;
    for(int i=0;i<n;i++){
        if(d>abs(p[i].num-a)){
            d = abs(p[i].num-a);
            k = i;
        }
    }
    printf("%d %s\n",a,p[k].name);
}

L1-058 6翻了 (15 分)

“666”是一种网络用语,大概是表示某人很厉害、我们很佩服的意思。最近又衍生出另一个数字“9”,意思是“6翻了”,实在太厉害的意思。如果你以为这就是厉害的最高境界,那就错啦 —— 目前的最高境界是数字“27”,因为这是 3 个 “9”!

本题就请你编写程序,将那些过时的、只会用一连串“6666……6”表达仰慕的句子,翻译成最新的高级表达。

输入格式:
输入在一行中给出一句话,即一个非空字符串,由不超过 1000 个英文字母、数字和空格组成,以回车结束。

输出格式:
从左到右扫描输入的句子:如果句子中有超过 3 个连续的 6,则将这串连续的 6 替换成 9;但如果有超过 9 个连续的 6,则将这串连续的 6 替换成 27。其他内容不受影响,原样输出。

输入样例:
it is so 666 really 6666 what else can I say 6666666666
输出样例:
it is so 666 really 9 what else can I say 27

  1. 读入的字符串不会自动加’\0’,要用到’\0’的话还得自己手动加
  2. 刚开始用while:我本来想的是把最后的回车也读进去,最后直接判断输出num判断后的字符串再加回车,回车读入之后再判断下一个读入的时候为空再退出while,但是事实是回车读入后就不能再进while了,用NULL来判断读取的字符是否为空也行不通
#include<bits/stdc++.h>
using namespace std;
int main(){
    string str;
    int num=0;
    getline(cin,str);
    str += '\0'; // 读入的字符串不会自动加'\0',要用到'\0'的话还得自己手动加
    char s;
//     while((s=getchar()) != NULL){ 
    for(int i=0;i<str.length();i++){
        s = str[i];
        if(s=='6'){
            num++;
            continue;
        }else{
            if(num>9){
                cout << "27" ;
            }
            else if(num>3){
                cout << "9" ;
            }
            else if(num>0&&num<=3){
                for(int i=0;i<num;i++) cout<<'6';
            }
            num = 0;
            cout << s;
        }
    }
    cout << endl;
}

L1-059 敲笨钟 (20 分)

微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。为了增加敲钟的趣味性,还会糟改几句古诗词。其糟改的方法为:去网上搜寻压“ong”韵的古诗词,把句尾的三个字换成“敲笨钟”。例如唐代诗人李贺有名句曰:“寻章摘句老雕虫,晓月当帘挂玉弓”,其中“虫”(chong)和“弓”(gong)都压了“ong”韵。于是这句诗就被糟改为“寻章摘句老雕虫,晓月当帘敲笨钟”。

现在给你一大堆古诗词句,要求你写个程序自动将压“ong”韵的句子糟改成“敲笨钟”。

输入格式:
输入首先在第一行给出一个不超过 20 的正整数 N。随后 N 行,每行用汉语拼音给出一句古诗词,分上下两半句,用逗号 , 分隔,句号 . 结尾。相邻两字的拼音之间用一个空格分隔。题目保证每个字的拼音不超过 6 个字符,每行字符的总长度不超过 100,并且下半句诗至少有 3 个字。

输出格式:
对每一行诗句,判断其是否压“ong”韵。即上下两句末尾的字都是“ong”结尾。如果是压此韵的,就按题面方法糟改之后输出,输出格式同输入;否则输出 Skipped,即跳过此句。

输入样例:

5
xun zhang zhai ju lao diao chong, xiao yue dang lian gua yu gong.
tian sheng wo cai bi you yong, qian jin san jin huan fu lai.
xue zhui rou zhi leng wei rong, an xiao chen jing shu wei long.
zuo ye xing chen zuo ye feng, hua lou xi pan gui tang dong.
ren xian gui hua luo, ye jing chun shan kong.

输出样例:

xun zhang zhai ju lao diao chong, xiao yue dang lian qiao ben zhong.
Skipped
xue zhui rou zhi leng wei rong, an xiao chen jing qiao ben zhong.
Skipped
Skipped
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    cin.ignore();
    while(n--){
        string s;
        getline(cin,s);
        int l = s.length();
        int ok = 0;
        int indent=0;
        int j;
        if(s[l-2]=='g'&&s[l-3]=='n'&&s[l-4]=='o'){
            for(int i=l-1;i>=0;i--){
                if(s[i]==' ') {
                    indent++;
                    if(indent==3) j = i; //倒数第三个字前面的空格的位置
                }
                if(s[i]==','){
                    if(s[i-1]=='g'&&s[i-2]=='n'&&s[i-3]=='o'){
                        ok=1;
                        s.replace(j,l-j," qiao ben zhong.");
                        cout << s << endl;
                    }
                    break;
                } 
            }
        }
        if(!ok){
            cout<<"Skipped"<<endl;
        }
//         cin.ignore(); //此处不用吸收,不然下一行的第一个字符会被这句吸收
    }
}

C++中string 的replace用法

L1-064 估值一亿的AI核心代码 (20 分)

AI.jpg

以上图片来自新浪微博。

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:

无论用户说什么,首先把对方说的话在一行中原样打印出来;
消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
把原文中所有大写英文字母变成小写,除了 I;
把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词;
把原文中所有独立的 I 和 me 换成 you;
把原文中所有的问号 ? 换成惊叹号 !;
在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。

输出格式:
按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。

输入样例:
6
Hello ?
Good to chat with you
can you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
输出样例:
Hello ?
AI: hello!
Good to chat with you
AI: good to chat with you
can you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don’t know

思路:先用stringstream整理好字符串的格式(空格和大小写),再用正则表达式替换需要替换的项

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    cin.ignore();
    while(n--){
        string str;
        getline(cin,str);
        cout << str << endl;
        cout << "AI: " ;
        
        stringstream ss(str); //stringstream接收可以整个字符串(不管含不含空格)都接受
        string s;
        int cnt=0;
        
        while(ss>>str){ //stringstream输出会以空格做为间断输出
            if(isalnum(str[0])){ //如果该部分不是整字符串的开头且第一个字符不是标点,就要加空格
                if(cnt) s += " ";
            }
            cnt = 1;
            s += str;
        }//while
        
        int l = s.length();
        for(int i=0;i<l;i++){ //转换大小写
            if(s[i]!='I'&&isalnum(s[i])) s[i] = tolower(s[i]); //转换为小写
        }
        //`\b`用于匹配一个单词边界,即字与空格间的位置。
        s = regex_replace(s,regex(R"(\bI\b)"),"&&&"); //将I me替换为&&&,避免影响can you和could you
        s = regex_replace(s,regex(R"(\bme\b)"),"&&&");
        s = regex_replace(s,regex(R"(\bcan you\b)"),"I can"); 
        s = regex_replace(s,regex(R"(\bcould you\b)"),"I could");
        s = regex_replace(s,regex(R"(&&&)"),"you");
        s = regex_replace(s,regex(R"(\?)"),"!");
        
        cout << s << endl;
    }//while
}

参考链接:

  1. isalnum()判断一个字符是否是字母或数字
  2. stringstream常见用法介绍
  3. 借鉴了大佬和评论区大佬的代码:
    PTA 估值一亿的AI核心代码(全网最短的代码)不到50行,一看就会
  4. 正则表达式

做的关于stringstream的一个小测试:
在这里插入图片描述

L1-068 调和平均 (10 分)

N 个正数的算数平均是这些数的和除以 N,它们的调和平均是它们倒数的算数平均的倒数。本题就请你计算给定的一系列正数的调和平均值。

输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出正整数 N (≤1000);第 2 行给出 N 个正数,都在区间 [0.1,100] 内。

输出格式:
在一行中输出给定数列的调和平均值,输出小数点后2位。

输入样例:
8
10 15 12.7 0.3 4 13 1 15.6
输出样例:
1.61

????: 一开始读数用的是while(n--),跑不过,检查过读数(不管是scanf还是cin)是没有问题的,但是结果出来就是不对,不知道为什么。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin >> n;
    cin.ignore();
    double sum=0,a;
    for(int i=0;i<n;i++){
        scanf("%lf",&a);
        sum += 1/a;
    }
    sum = n/sum;
    printf("%0.2f\n",sum);
}

L1-069 胎压监测 (15 分)

小轿车中有一个系统随时监测四个车轮的胎压,如果四轮胎压不是很平衡,则可能对行车造成严重的影响。

taiya.JPG

让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序,随时监测四轮的胎压,并给出正确的报警信息。报警规则如下:

如果所有轮胎的压力值与它们中的最大值误差在一个给定阈值内,并且都不低于系统设定的最低报警胎压,则说明情况正常,不报警;
如果存在一个轮胎的压力值与它们中的最大值误差超过了阈值,或者低于系统设定的最低报警胎压,则不仅要报警,而且要给出可能漏气的轮胎的准确位置;
如果存在两个或两个以上轮胎的压力值与它们中的最大值误差超过了阈值,或者低于系统设定的最低报警胎压,则报警要求检查所有轮胎。
输入格式:
输入在一行中给出 6 个 [0, 400] 范围内的整数,依次为 1~4 号轮胎的胎压、最低报警胎压、以及胎压差的阈值。

输出格式:
根据输入的胎压值给出对应信息:

如果不用报警,输出 Normal;
如果有一个轮胎需要报警,输出 Warning: please check #X!,其中 X 是出问题的轮胎的编号;
如果需要检查所有轮胎,输出 Warning: please check all the tires!。
输入样例 1:
242 251 231 248 230 20
输出样例 1:
Normal
输入样例 2:
242 251 232 248 230 10
输出样例 2:
Warning: please check #3!
输入样例 3:
240 251 232 248 240 10
输出样例 3:
Warning: please check all the tires!

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a[4],n,m;
    for(int i=0;i<4;i++){
        cin >> a[i];
    }
    cin>>n>>m;
    int sum=0;
    int b = *max_element(a,a+4); //求数组中的最大值
    int j;
    for(int i=0;i<4;i++){
        if(abs(a[i]-b)>m || a[i]<n){
            sum++;
            j = i;
        }
    }
    if(sum==0) printf("Normal\n");
    else if(sum==1) printf("Warning: please check #%d!",j+1);
    else printf("Warning: please check all the tires!\n");
}

L1-070 吃火锅 (15 分)

以上图片来自微信朋友圈:这种天气你有什么破事打电话给我基本没用。但是如果你说“吃火锅”,那就厉害了,我们的故事就开始了。

本题要求你实现一个程序,自动检查你朋友给你发来的信息里有没有 chi1 huo3 guo1。

输入格式:
输入每行给出一句不超过 80 个字符的、以回车结尾的朋友信息,信息为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。当读到某一行只有一个英文句点 . 时,输入结束,此行不算在朋友信息里。

输出格式:
首先在一行中输出朋友信息的总条数。然后对朋友的每一行信息,检查其中是否包含 chi1 huo3 guo1,并且统计这样厉害的信息有多少条。在第二行中首先输出第一次出现 chi1 huo3 guo1 的信息是第几条(从 1 开始计数),然后输出这类信息的总条数,其间以一个空格分隔。题目保证输出的所有数字不超过 100。

如果朋友从头到尾都没提 chi1 huo3 guo1 这个关键词,则在第二行输出一个表情 -_-#。

输入样例 1:
Hello!
are you there?
wantta chi1 huo3 guo1?
that’s so li hai le
our story begins from chi1 huo3 guo1 le
.
输出样例 1:
5
3 2
输入样例 2:
Hello!
are you there?
wantta qi huo3 guo1 chi1huo3guo1?
that’s so li hai le
our story begins from ci1 huo4 guo2 le
.
输出样例 2:
5
-_-#

找到子串:string.find(str)!=string.npos.
(记忆小贴士:npos,即no position)
C++字符串的find

#include<bits/stdc++.h>
using namespace std;
vector<string> s;
int main(){
    int i=0,sum=0,flag=0;
    while(true){
        string a;
        getline(cin,a);
        if(a==".") break;
        s.push_back(a);
        if(a.find("chi1 huo3 guo1") != a.npos){ //如果找到
            if(!flag){
                flag = 1;
                i = s.size(); //第一次出现的位置
            }
            sum++;
        }
    }
    if(sum==0){
            printf("%u\n-_-#\n",s.size());
        }else{
            printf("%u\n%d %d\n",s.size(),i,sum);
        }
}

L1-071 前世档案 (20 分)

qs.jpg

网络世界中时常会遇到这类滑稽的算命小程序,实现原理很简单,随便设计几个问题,根据玩家对每个问题的回答选择一条判断树中的路径(如下图所示),结论就是路径终点对应的那个结点。

path.jpg

现在我们把结论从左到右顺序编号,编号从 1 开始。这里假设回答都是简单的“是”或“否”,又假设回答“是”对应向左的路径,回答“否”对应向右的路径。给定玩家的一系列回答,请你返回其得到的结论的编号。

输入格式:
输入第一行给出两个正整数:N(≤30)为玩家做一次测试要回答的问题数量;M(≤100)为玩家人数。

随后 M 行,每行顺次给出玩家的 N 个回答。这里用 y 代表“是”,用 n 代表“否”。

输出格式:
对每个玩家,在一行中输出其对应的结论的编号。

输入样例:
3 4
yny
nyy
nyn
yyn
输出样例:
3
5
6

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m;
    cin >> n>>m;
    cin.ignore();  //吸收大法!!!!!!
    for(int i=0;i<m;i++){
        int high = pow(2,n),low=1,mid;
        for(int j=0;j<n;j++){
            char c = getchar();
            mid = (high+low)/2;
            if(c=='y'){
                high = mid;
                if(j==n-1) cout<<high<<endl;
            }else if(c=='n'){
                low = mid+1;
                if(j==n-1) cout<<low<<endl;
            }
        }
		cin.ignore();
    }
    return 0;
}

L1-072 刮刮彩票 (20 分)

“刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示:

-362960_55cb6a89bf693.png

每次游戏玩家会拿到一张彩票,上面会有 9 个数字,分别为数字 1 到数字 9,数字各不重复,并以 3×3 的“九宫格”形式排布在彩票上。

在游戏开始时能看见一个位置上的数字,其他位置上的数字均不可见。你可以选择三个位置的数字刮开,这样玩家就能看见四个位置上的数字了。最后玩家再从 3 横、3 竖、2 斜共 8 个方向中挑选一个方向,方向上三个数字的和可根据下列表格进行兑奖,获得对应数额的金币。

数字合计 获得金币 数字合计 获得金币
6 10,000 16 72
7 36 17 180
8 720 18 119
9 360 19 36
10 80 20 306
11 252 21 1,080
12 108 22 144
13 72 23 1,800
14 54 24 3,600
15 180
现在请你写出一个模拟程序,模拟玩家的游戏过程。

输入格式:
输入第一部分给出一张合法的彩票,即用 3 行 3 列给出 0 至 9 的数字。0 表示的是这个位置上的数字初始时就能看见了,而不是彩票上的数字为 0。

第二部给出玩家刮开的三个位置,分为三行,每行按格式 x y 给出玩家刮开的位置的行号和列号(题目中定义左上角的位置为第 1 行、第 1 列。)。数据保证玩家不会重复刮开已刮开的数字。

最后一部分给出玩家选择的方向,即一个整数: 1 至 3 表示选择横向的第一行、第二行、第三行,4 至 6 表示纵向的第一列、第二列、第三列,7、8分别表示左上到右下的主对角线和右上到左下的副对角线。

输出格式:
对于每一个刮开的操作,在一行中输出玩家能看到的数字。最后对于选择的方向,在一行中输出玩家获得的金币数量。

输入样例:
1 2 3
4 5 6
7 8 0
1 1
2 2
2 3
7
输出样例:
1
5
6
180

本来是想用字典的形式来存最后兑换的金币的,但是因为“键值”是连续的,用数组的索引来对应值要更方便一些。如果“键值”是离散的就应该用字典。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int ma[50]={10000,36,720,360,80,252,108,72,54,180,72,180,119,36,306,1080,144,1800,3600};
    int a[3][3],n,d[10]={0};
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            cin >> a[i][j];
            int c = a[i][j];
            d[c]++;
        }
        cin.ignore();
    }
    int val; //刚开始能看到的值
    for(int i=0;i<10;i++){
        if(d[i]==0) val=i;
    }
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            if(a[i][j]==0) a[i][j]=val;
        }
    }
    for(int i=0;i<3;i++){
        int x,y;
        cin >> x >> y;
        cout << a[x-1][y-1] << endl;
        cin.ignore();
    }
    cin >> n;
    int sum=0;
    if(n<=3){
        for(int i=0;i<3;i++){
            sum+=a[n-1][i];
        }
    }else if(n>=4&&n<=6){
        for(int i=0;i<3;i++){
            sum+=a[i][n-4];
        }
    }else if(n==7){
        for(int i=0;i<3;i++){
            sum+=a[i][i];
        }
    }else if(n==8){
        for(int i=0;i<3;i++){
            sum+=a[i][2-i];
        }
    }
    cout << ma[sum-6] << endl;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值