xjoi 1级21段题解 c++

这篇文章包含了多个C++编程题目,包括扫雷游戏的实现、友好数对的统计、垂直柱状图的绘制、字符串处理、围棋布局分析、子矩阵求和问题、电影院购票找零问题、进制转换算法以及质因数分解等,展示了C++在解决各种算法问题上的应用。
摘要由CSDN通过智能技术生成
#include<bits/stdc++.h>
using namespace std;
#define H 3
#define W 4
char a[500][1001];
char c[H][W+1]={" O  ",
             "/|\\ ",
             "/ \\ "};
int main() {
    int n;
    cin>>n;
    memset(a, ' ', sizeof(a));
    for(int r=1;r<=n;r++){
        for(int p=1; p<=r; p++) {
            for(int i=0;i<H;i++){
                for(int j=0;j<W;j++){
                        a[(r-1)*H+i][(n-r)*W+2*(p-1)*W+j]=c[i][j];
                }
            }
        }
    }
    for(int i=0;i<H*n;i++){
        for(int j=0;j<(2*H*n+1)*W;j++){
            cout<<a[i][j];
        }
        cout<<endl;
    }
    return 0;
}

1.扫雷游戏

时间:1s   空间:256M

题目描述:

扫雷游戏是一款十分经典的单机小游戏。在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。

现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。

注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。

输入格式:

第一行输入两个整数n,m ,分别表示雷区的行数和列数。

接下来n行,每行m个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。

输出格式:

输出包含n行,每行m个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。

样例输入1
3 3
*??
???
?*?

样例输出1
*10
221
1*1

样例输入2
2 3
?*?
*??

样例输出2
2*1
*21

约定:

1<=n,m<=100

 c++AC代码 : 

#include <iostream>
#include <cstdio>
#define N 103
void search(int i,int j);
char a[N][N];
int n,m;
int main()  {
    scanf("%d %d",&n,&m);
    getchar();
    for (int i=0;i<n;i++)   {
        for (int j=0;j<m;j++)
            scanf("%c",&a[i][j]);
        getchar();
    }
    for (int i=0;i<n;i++)   {
        for (int j=0;j<m;j++)   {
            if (a[i][j]=='*')
                printf("*");
            else
                search(i,j);
            if (j+1==m) printf("\n");
        }
    }
    return 0;
}
void search(int i,int j)    {
    int flag=0;
    for (int di=-1;di<2;di++)
        for (int dj=-1;dj<2;dj++)
            {
                int x=i+di;
                int y=j+dj;
                if ((di!=0||dj!=0)&&x>=0&&x<n&&y>=0&&y<m)
                    if (a[x][y]=='*')
                        flag++;
            }
    printf("%d",flag);
}

2.友好数对

题目描述:

读入一个n*m的矩阵,定义两个数是友好的,当且仅当他们位置相邻(上下左右)且值相同。求友好数对个数。

输入格式:

第一行两个整数n,m

之后n行,每行m个0到100间的整数

输出格式:

一个整数,表示答案。

样例输入1:

5 4

3 3 3 4

2 0 0 3

0 3 1 4

3 4 3 3

1 0 3 3

样例输出1:

7

约定:

1<=n,m<=500

c++AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
  
    int n,m,a[505][505];
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++) cin>>a[i][j];
    }
    int ans=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(j>0){
                if(a[i][j]==a[i][j-1]) ans++;
            }
            if(i>0){
                if(a[i][j]==a[i-1][j]) ans++;
            }
        }
    }
    cout<<ans;
  
    return 0;
}

3.垂直柱状图

题目描述:

写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过100个字符),然后用柱状图输出每个字符在输入文件中出现的次数。严格地按照输出样例来安排你的输出格式。

输入格式:

四行字符,由大写字母组成,每行不超过100个字符

输出格式:

由若干行组成,前几行由空格和星号组成,最后一行则是由空格和字母组成的。不要打印任何空行。

样例输入1

THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG.
THIS IS AN EXAMPLE TO TEST FOR YOUR
HISTOGRAM PROGRAM.
HELLO!

样例输出1

                            *
                            *
        *                   *
        *                   *     *   *
        *                   *     *   *
*       *     *             *     *   *
*       *     * *     * *   *     * * *
*       *   * * *     * *   * *   * * * *
*     * * * * * *     * * * * *   * * * *     * *
* * * * * * * * * * * * * * * * * * * * * * * * * *
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

c++AC代码 : 

#include<iostream>
#include<string>
using namespace std;
int Max(int* a);//找出所出现字母当中出现次数最多的字母并返回其值
void Display(int max,int* a);//展?输出的?式
int main()
{
string str;
int a[26]={0};
for(int i =0; i <4; i++)
{
getline(cin, str);
for(int j =0; j <= str.length(); j++)
{
if(str[j]>='A'&& str[j]<='Z')
{
a[str[j]-'A']++;
}
}
}
int max =Max(a);
Display(max, a);
return 0;
}
int Max(int* a)//找出所出现字母当中出现次数最多的字母并返回其值
{
int max =0;
for(int i =0; i <26; i++)
{
if(max < a[i])
{
max = a[i];
}
}
return max;
}
void Display(int max,int* a)//展?输出的?式
{
for(int i = max; i >0; i--)
{
for(int j =0; j <26; j++)
{
if(a[j]>= i)
{
cout <<"* ";
}
else{
cout <<"  ";
}
}
cout << endl;
}
for(int i =0; i <26; i++)
{
char c = i +'A';
cout << c <<" ";
}
}

4.爱丽丝的卡片

时间:0.2s   空间:32M

题目描述:

爱丽丝有一个由小写字母构成的字符串,字符串被写在了墙上。

同时,她还有一堆卡片,每张卡片上写着一个字母,爱丽丝可以取出若干张卡片,覆盖墙上的一些字母。(也可以一张都不取)

她希望覆盖之后新的字符串字典序尽可能大。帮她找出覆盖之后字典序最大的字符串吧。

输入格式:

第一行输入一个字符串,表示墙上的字符串。

第二行输入一个字符串,表示爱丽丝手上拥有的字母。

输出格式:

输出一行,包含一个字符串

样例输入:
fedcba
ee
样例输出:
feeeba

约定:

字符串长度<=50,都由小写字母构成

c++AC代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
  
int main() {
    string wall, cards;
    cin >> wall >> cards;
    sort(cards.rbegin(), cards.rend());
  
    int i = 0, j = 0;
    while (i < wall.length() && j < cards.length()) {
        if (cards[j] > wall[i]) {
            wall[i] = cards[j];
            j++;
        }
        i++;
    }
  
    cout << wall << endl;
  
    return 0;
}

5.数组-围棋

时间:1s   空间:256M

题目描述:

给你一个黑白棋盘,棋盘上有些位置已经放了黑子或者白子,现在问你,有没有一种放置方案可以用黑子或者白子放满整个棋盘,使得没有两个相邻的格点放了同色的棋子。

输入格式:

多组测试数据

每组数据

第一行输入两个整数n,m

接下来n行每行输入一个长度为m的字符串.

一共有’W’, ‘B’, ‘?’三种字符,W表示白子,B表示黑子。’?’表示还没有放子

输出格式:

如果存在一种方案,输出”Possible”

如果不存在输出”Impossible”

样例输入:
3 3
W?W
??B
???
3 2
W?
??
B?
样例输出:
Possible
Impossible

约定:

1<=n,m<=100
c++AC代码:

#include <iostream>
using namespace std;
  
int main()
{
    int n, m;
    while(cin>>n>>m){
        char a;
        int assign = 0;
        char start = 'B';
        bool flag=false;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {       
                cin >> a;
                if (a != '?')
                {
                    if (assign == 0)
                    {               
                        assign = 1;
                        start = (i + j) % 2 == 0 ? a : (a == 'B' ? 'W' : 'B');
                    }
                    else
                    {
                        char c = (i + j) % 2 == 0 ? start : (start == 'B' ? 'W' : 'B');
                        if (c != a)
                        {
                            flag=true;
                        }
                    }
                }
            }
        if(flag) cout << "Impossible" << endl;
        else cout << "Possible" << endl;
    }
     
    return 0;
}

6.子矩阵求和

题目描述:

读入一个n*m的矩阵,q次询问,每次询问一个子矩阵内数字权值和。


 

输入格式:

第一行三个整数n,m,q

之后n行每行m个0到100的整数

之后q行,每行四个整数x1,y1,x2,y2,表示要询问的子矩阵。

输出格式:

q行表示答案。


 

样例输入1

5 4 1

1 1 0 0

1 0 0 0

0 0 1 1

1 1 1 1

1 0 1 0

2 2 5 3

样例输出1

4


 

约定:

1<=n,m<=500, q<=1000000

c++AC代码:

#include<cstdio>
#include<vector>
using namespace std;
vector<int> map[100100];
int main(){
int N,M,Q,x;
scanf("%d%d",&N,&M);
scanf("%d",&Q);
for(int i=0;i<=M;i++) map[0].push_back(0);//初始化
for(int i=1;i<=N;i++){
map[i].push_back(0);
for(int j=1;j<=M;j++){
scanf("%d",&x);
map[i].push_back(map[i][j-1]+map[i-1][j]+x-map[i-1][j-1]);
}
}
int x1,y1,x2,y2;
while(Q--){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ans=map[x2][y2]-map[x2][y1-1]-map[x1-1][y2]+map[x1-1][y1-1];
printf("%d\n",ans);    }
return 0;
}

7.学军电影院

时间:1s   空间:256M

题目描述:

学军电影院暑期档大片“学军熊猫”正在热映,票价25元,现在有很多oier即将来买票,oier都是极简主义者,因此每个人手里只有一张纸币,纸币的面值是100,50,25当中的一种,学军中学已经实现了自动售票,电影院门口放了一台自动售票机,但不巧的是,今天自动售票机里面没有零钱了,现在问你,已知n个oier所带的纸币的信息,以及他们到来的顺序,自动售票机能否在没有钱的情况下完成找钱功能。

(假设纸币投入机器后,会在下一个买票人之前,由工作人员换为对应数量的1元零钱。例如第一个人将1张25元的纸币投入机器后,在第二个人买票时,机器里是25个1元的零钱)

输入格式:

多组测试数据。

每组测试数据先输入一个n,表示买票的总人数,接下来一行输入n个正整数。表示每个人手里的纸币面值。

输出格式:

对于每组测试数据

输出”YES”,如果可以完成找钱功能

输出”NO”,如果不能完成找钱功能。

样例输入:
4
25 25 50 50
2
25 100
4
50 50 25 25

样例输出:
YES
NO
NO

约定:

1<=n<=105

提示:

第一组数据:先来了两个人手里都有25元钱,都不用找,现在机器里面一共有了两张25,接下来两个人手里都有一张50,每个人分别找回去25。找钱成功。

第二组数据:第一个人来,不用找钱,第二个人来,要找75,发现零钱不够了,所以找钱失败。

第三组数据:第一个人给50,机器里面一开始没有钱,没法找零,所以找钱失败。

 c++AC代码:

#include <iostream>
#include <vector>
using namespace std;
int cnt, n;
int main() {
    while(cin >> n) {
        vector <int>bills(n);
        for (int i = 0; i < n; i++) {
            cin >> bills[i];
        }
        int numOf25 = 0, numOf50 = 0;
        bool flag = true;
        for (int i = 0; i < n; i++) {
            if (bills[i] == 25) {
                numOf25++;
            } else if (bills[i] == 50) {
                if (numOf25 > 0) {
                    numOf25--;
                    numOf50++;
                } else {
                    flag = false;
                    break;
                }
            } else if (bills[i] == 100) {
                if (numOf50 > 0 && numOf25 > 0) {
                    numOf50--;
                    numOf25--;
                } else if (numOf25 >= 3) {
                    numOf25 -= 3;
                } else {
                    flag = false;
                    break;
                }
            }
        }
        if (flag) {
            cout << "YES" << endl;
        } else {
            cout << "NO" << endl;
        }
    }
    return 0;
}

8.进制转换

请你编一程序实现两种不同进制之间的数据转换。

输入格式:

输入数据共有三行,第一行是一个正整数,表示需要转换的数的进制n(2≤n≤16),第二行是一个n进制数,若n>10则用大写字母A~F表示数码10~15,并且该n进制数对应的十进制的值不超过1000000000,第三行也是一个正整数,表示转换之后的数的进制m(2≤m≤16)。

输出格式:

输出仅一行,包含一个正整数,表示转换之后的m进制数。

样例输入:

16
FF
2

样例输出:

11111111

数据范围:

见题目

时间限制:

1000

空间限制:

65536

c++AC代码:

#include <iostream>
#include <string>
#include <cmath>
using namespace std;
 
int convertToDecimal(string num, int base) {
    int result = 0;
    int len = num.length();
    for (int i = len - 1; i >= 0; i--) {
        int digit;
        if (num[i] >= '0' && num[i] <= '9') {
            digit = num[i] - '0';
        } else {
            digit = num[i] - 'A' + 10;
        }
        result += digit * pow(base, len - 1 - i);
    }
    return result;
}
 
string convertToBase(int num, int base) {
    string result = "";
    while (num > 0) {
        int digit = num % base;
        char c;
        if (digit < 10) {
            c = digit + '0';
        } else {
            c = digit - 10 + 'A';
        }
        result = c + result;
        num = num / base;
    }
    return result;
}
 
int main() {
    int n, m;
    string num;
    cin >> n;
    cin >> num;
    cin >> m;
 
    int decimal = convertToDecimal(num, n);
    string result = convertToBase(decimal, m);
    cout << result << endl;
 
    return 0;
}

9.循环-分解质因式

时间:1s   空间:256M

题目描述:

正整数分解为质因式,输出如下形式:如

2=2, 3=3, 4=2^2 , 5=5, 6=2*3 ,100=2^2*5^2

输入格式:

输入一行,包含一个正整数n

输出格式:

输出n的质因式表达

样例输入:
2

样例输出:
2=2

约定:

1<=n<=1000

c++AC代码:

#include <iostream>
using namespace std;
 
int primeFactorization(int n) {
    if (n == 1) {
        cout << "1=1";
        return 0;
    }
cout << n << "=";
    for (int i = 2; i <= n; i++) {
        int count = 0;
        while (n % i == 0) {
            count++;
            n /= i;
        }
        if (count > 0) {
            cout << i;
            if (count > 1) {
                cout << "^" << count;
            }
            if (n > i) {
                cout << "*";
            }
        }
    }
    cout << endl;
}
 
int main() {
    int n;
    cin >> n;
    primeFactorization(n);
    return 0;
}

10.数组-炸弹

时间:1s   空间:256M

题目描述:

一个月黑风高的晚上你接到了一个爆破任务,有一个n∗m的场地,有些地方有墙,假如你在(i,j)位置投放一个炸弹,第i行和第j列的墙都会被炸毁,现在你想知道是否可以只投放一次炸弹就将所有的墙炸掉。保证至少有一面墙。

输入格式:

第一行一个整数T,表示测试数据的组数

每组数据的

第一行,包含两个整数 n,m

接下来n行,每行m个字符,’*’ 表示墙,’.’表示空地。

输出格式:

如果可以一次炸毁所有的墙在第一行输出“YES”,否则输出”NO”

如果可以一次炸毁所有的墙,在第二行输出投放炸弹的位置x,y

如果有多个位置可以炸毁,输出行号最小的,如果还有多个行号一样小的,输出列标号最小的。

样例输入:
2
3 4
.*..
....
.*..

3 3
..*
.*.
*..
样例输出:
YES
1 2
NO

约定:

1<=n,m<=1000

c++AC代码:

#include<iostream>
using namespace std;
int t,n,m,sum;
char k;
int x[1010],y[1010],a,b;
bool g[1010][1010],temp;
int main()
{
    cin>>t;
    for(int ti=1;ti<=t;ti++)
    {
        for(int i=1;i<1010;i++)
            x[i]=0;
        for(int i=1;i<1010;i++)
            y[i]=0;
        for(int i=1;i<1010;i++)
            for(int j=1;j<1010;j++)
                g[i][j]=0;
        temp=sum=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>k;
                if(k=='*')
                {
                    x[i]++;                         //炸弹所在的纵行,每有一个+1
                    y[j]++;                         //炸弹所在的横行,每有一个+1
                    g[i][j]=1;
                    sum++;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(x[i]+y[j]-g[i][j]==sum)
                {
                    a=i;b=j;
                    temp=1;
                    break;
                }
            }
            if(temp) break;
        }
        if(temp==0)cout<<"NO"<<endl;
        else
        {
            cout<<"YES"<<endl;
            cout<<a<<" "<<b<<endl;
        }
    }
    return 0;
}

11.人山人海

时间:1s   空间:32M

题目描述:

还记得打印金字塔的题目么?

今天让我们来打印人形金字塔,感受下人山人海的力量。

输入一个整数n

输出n层的金字塔,第i层有i个人,注意两个人之间的空隙大小

注:请尽量使用编程的思维解决问题,当然如果你一定要手打出来,我也不会拦着你。。。。

输入格式:

输出一个整数n

输出格式:

输出n层人形金字塔

样例输入1:
2

样例输出1:
     O
    /|\ 
    / \
 O       O
/|\     /|\ 
/ \     / \

样例输入2:
4

样例输出2:
             O 
            /|\
            / \
         O       O 
        /|\     /|\
        / \     / \
     O       O       O 
    /|\     /|\     /|\
    / \     / \     / \
 O       O       O       O 
/|\     /|\     /|\     /|\
/ \     / \     / \     / \

约定:

1<=n<=10

c++AC代码:

#include<bits/stdc++.h>
using namespace std;
#define H 3
#define W 4
char a[500][1001];
char c[H][W+1]={" O  ",
             "/|\\ ",
             "/ \\ "};
int main() {
    int n;
    cin>>n;
    memset(a, ' ', sizeof(a));
    for(int r=1;r<=n;r++){
        for(int p=1; p<=r; p++) {
            for(int i=0;i<H;i++){
                for(int j=0;j<W;j++){
                        a[(r-1)*H+i][(n-r)*W+2*(p-1)*W+j]=c[i][j];
                }
            }
        }
    }
    for(int i=0;i<H*n;i++){
        for(int j=0;j<(2*H*n+1)*W;j++){
            cout<<a[i][j];
        }
        cout<<endl;
    }
    return 0;
}

12.上网

时间:0.2s   空间:32M

题目描述:

现在三种浏览网页的行为,跟我们平时上网情景一样

visit: 访问某个特定的网址,相当于我们在当前页面的地址栏输入一个url

back: 回到上一次访问的网址,相当于下图中的左箭头

forward: 相当于下图中的右箭头。

要注意,一旦visit操作之后,右箭头就会消失,因为刚才输入的网址已经是最新网址,没有更新的了,可以自己试试再来做这个题。

假设一开始正在访问的第一个网址为http://www.hzxjhs.com/

输入格式:

输入若干行,碰到"QUIT"结束,表示关闭浏览器

其他一共三种输入类型。

VISIT 操作后面会跟一个字符串,表示网址

BACK

FORWARD

输出格式:

对于每个操作,输出当前访问的网址,若操作非法,输出"Ignored"

样例输入:
VISIT http://www.codeforces.com/
VISIT http://www.topcoder.com/
BACK
BACK
BACK
FORWARD
VISIT http://www.codechef.com/
BACK
BACK
FORWARD
FORWARD
FORWARD
QUIT
样例输出:
http://www.codeforces.com/
http://www.topcoder.com/
http://www.codeforces.com/
http://www.hzxjhs.com/
Ignored
http://www.codeforces.com/
http://www.codechef.com/
http://www.codeforces.com/
http://www.hzxjhs.com/
http://www.codeforces.com/
http://www.codechef.com/
Ignored

约定:

所有的网址都没有空格,最长的网址为70

总的操作次数不超过1000

c++AC代码:

 

#include<bits/stdc++.h>
using namespace std;
string i, c = "http://www.hzxjhs.com/";
int main() {
    stack<string> h;
    stack<string> f;
    while (getline(cin, i)) {
        if (i == "QUIT") {
            break;
        } else if (i.substr(0, 5) == "VISIT") {
            string url = i.substr(6);
            h.push(c);
            c = url;
            while (!f.empty()) {
                f.pop();
            }
            cout << c << endl;
        } else if (i == "BACK") {
            if (h.empty()) {
                cout << "Ignored" << endl;
            } else {
                f.push(c);
                c = h.top();
                h.pop();
                cout << c << endl;
            }
        } else if (i == "FORWARD") {
            if (f.empty()) {
                cout << "Ignored" << endl;
            } else {
                h.push(c);
                c = f.top();
                f.pop();
                cout << c << endl;
            }
        }
    }
    return 0;
}

敬请期待xjoi1级20段题解

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值