目录
21.打死我也不说!
题目详情
梗:最好的密电码是啥? 是“打死我也不说!”这样,即使帮我们传送密电码的猪队友被敌人抓住严刑拷打,我们也不用担心泄露秘密。
现在稍微改进一下,我们把“打死我也不说”的拼音首字母“DSWYBS”藏在一个矩阵里,而代表“打”的字母
D
和代表“说”的字母S
所在的行列下标之和即是密码。对于给定的矩阵,请判断其中是否藏有“DSWYBS”,如果有,给出首末两个字母的下标并计算密码;如果没有,打印一行“DSWYBS”。
注意:
- 若藏有“DSWYBS”,则这串字母必是沿行、列或斜45度方向依次排列的。
- 题目保证输入的矩阵至多藏有一串“DSWYBS”。
- 矩阵左上角下标为(0,0)。
- 区分大小写。
- 题目保证输入的矩阵不含有类似这样的排列(即:仅有DSWYB五个字母,但是字母B与S相邻,可组成DSWYBS的排列 ) :
DSB WY
输入格式
第一行给出两个整数
M
、N
(均不大于15、不小于4),接下来M行,每行有N个字母或数字,以换行结束。
输出格式
如果输入矩阵中藏有“DSWYBS”,则输出三行,第一行和第二行分别是首字母
D
的下标和末字母S
的下标,先行下标
后列下标
,以一个空格间隔。第三行给出两个字母四项下标值之和。如果没藏有该串字母,则打印一行“DSWYBS”
输入样例
8 10
0x00z000d0
00aD00s000
00b0SWk000
000wcY000s
00000B0000
0000S00000
0000000000
0000000000
输出样例
1 3
5 4
13
代码及解析如下;
#include <stdio.h>
int n,m,flag=0;
int x1,y1,x2,y2;
char ch[7]={'1','D','S','W','Y','B','S'}; //将这6种情况存到数组,方便搜索
char s[20][20];
void dfs(int x,int y,int step){
int tx,ty;
//next数组为搜索下一个位置
int next[8][2]={{0,1},{1,0},{0,-1},{-1,0},{-1,-1},{-1,1},{1,-1},{1,1}};
//搜索了6次,也就是从D递归找到了D,结束递归
if(step==6){
x2=x;
y2=y;
flag=1;
return ;
}
//搜索下一个位置
for(int i=0;i<8;i++){
tx=x+next[i][0];
ty=y+next[i][1];
//如果能匹配上ch数组,就在进行下一步搜索
if(tx>=0&&tx<n&&ty>=0&&ty<m&&s[tx][ty]==ch[step+1]){
dfs(tx,ty,step+1);
}
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",&s[i]);
}
for(int i=0;i<n;i++){
for(int k=0;k<m;k++){
if(s[i][k]=='D') //如果遇到字符‘D’就开始搜索
dfs(i,k,1);
if(flag){ //找到满足条件的了
x1=i;
y1=k;
break;
}
}
if(flag)break;
}
if(flag){
printf("%d %d\n%d %d\n%d",x1,y1,x2,y2,x1+y1+x2+y2);
}
else printf("DSWYBS");
return 0;
}
22.Excel列名和列序号转换
题目详情
大家有没有留意过Excel表格中列名的规律呢?是这样的:
A B C ... Y Z AA AB AC ... AY AZ BA BB BC ... BY BZ ... ZZ ... AAA ...
如果没看懂,请打开Excel程序仔细观察一下~~
每一列都是有序号的,从1
开始编号,即:列A B C ... Y Z AA AB ...
的编号依次是1 2 3 ... 25 26 27 28 ...
现在,请编写程序,按照上述规律,把输入的列名和列序号进行相互转换(不用考虑Excel软件实际允许的最多列数)。
输入格式
输入由若干行组成,每行的内容是以下三种之一:
- 长度不超过6的由大写字母组成的字符串,表示一个列名
- 不超过9位数字的正整数,表示一个列序号
- 符号
#
,表示输入结束
输出格式
对于在输入结束符
#
之前出现的每一行输入,若输入为列名,在一行内打印对应的列序号;若输入为列序号,在一行内打印对应的列名。
输入样例
A
3
AB
29
#
输出样例
1
C
28
AC
代码及解析如下:
//本质上是26进制与10进制的转换,然后要配合字符串和数组来实现
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
while(cin>>s,s[0]!='#'){
int p=0;
char c[100]; //用来存数字再转化的字母
int num=0,cnt=0;
for(int i=0;i<s.size();i++){
if(s[i]>='0'&&s[i]<='9'){ //如果输入的是数字
num=num*10+s[i]-'0'; //将数字字符全转为整形
}
else { //输入的是字母
p=1; //打个断点,方便后续判断
num=num*26+s[i]-'A'+1; //将字母字符转为整形,也就是将列名转为列序号
}
}
if(p)cout<<num<<endl; //如果输入的是字母,前面转化为数字后就可以直接输出了
else {
while(num){ //将数字再转换为字母字符
if(num%26==0){ //逢26进Z
c[cnt]='Z';
cnt++;
num/=26;
num--;
}
else {
c[cnt]='A'+num%26-1;
num/=26;
cnt++;
}
}
for(int j=cnt-1;j>=0;j--){ //因为先存的是每个num除26后的余数,所以要倒着输出
cout<<c[j];
}
cout<<endl;
}
}
}
23.高精度加法
题目详情
对于输入的两个不超过100位数字的非负整数,给出两数之和。
输入格式
在两行中分别给出两个不超过100位数字的非负整数
输出格式
在一行中输出两数之和
输入样例
123
12
输出样例
135
代码及解析如下:
模板题:高精度加、减、乘、除
#include <iostream>
#include <vector>
using namespace std;
vector<int> add(vector<int> &A,vector<int> &B)
{
vector<int> C;
int t=0;
for(int i=0;i<A.size()||i<B.size();i++)
{
if(i<A.size())t+=A[i];
if(i<B.size())t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t)C.push_back(1);
return C;
}
int main()
{
string a,b;
cin>>a>>b;
vector<int> A,B;
for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
auto C=add(A,B);
for(int i=C.size()-1;i>=0;i--)cout<<C[i];
}
24.N进制高精度加法
题目详情
到底应该怎样理解进制呢?首先得有“一个”的数量概念,然后就是这样的:
把用来表示数量的符号依次排列,例如: q w e r
然后定义最前面的符号为“零”,即“没有”,后面的符号表示的数量依次比前一个符号多“一个”
进制就这样产生了: 例如当我们数数,依次数到 q w e r ,再往后数一个,符号不够用了,那么就写成 wq
并且,我们把这种进制命名为“wq”进制。
感觉怪异吗? 那么请换成我们熟悉的所谓“10”进制看看:
我们的用于表示数量的符号依次是: 0 1 2 3 4 5 6 7 8 9 , 当数到9,再往后数“一个”时,就数到了 10
看这幅漫画(来源于网络),看看能不能理解“进制”的概念?
现在,给定表示数量的符号(这些符号就形成了某种进制),以及该种进制下的两个不超过100位的正整数,请计算两数之和。
输入格式
第一行给定表示数量的符号,每个符号为一个字符、各不相同且中间没有空格,最多有30个符号且符号的可能范围是:数字
0
-9
、大小写字母、!
、@
、#
、$
、%
、^
、&
、*
、(
、)
接下来两行每行给出一个该进制下的不超过100位的正整数
输出格式
在一行中输出该进制下的两数之和。
输入样例:
样例一:
0123456789
123
12样例二:
abcd
bcd
bc
输出样例
样例一:
135
样例二:cab
代码及解析如下:
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main()
{
string a,b,c; //用字符串的方式输入
cin>>a>>b>>c;
int len=a.size();
map<char,int> m; //把改进制下的每一位的下标用整形存储
reverse(b.begin(),b.end()); //从最低位开始加,所以反转一下
reverse(c.begin(),c.end());
for(int i=0;i<len;i++)
{
m[a[i]]=i; //存进制的下标
}
int i,t=0;
string d="";
for(i=0;i<b.size()||i<c.size();i++)
{
//两个字符串分别对应进制表的下标相加
if(i<b.size())t+=m[b[i]]; //
if(i<c.size())t+=m[c[i]];
d+=a[t%len]; //加和模上进制,使进位加到下一位
t/=len; //进位
}
if(t)d+=a[1]; //加完还有进位的话就再加一下
reverse(d.begin(),d.end()); //从最低位开始加,所以末尾输出的是高位
cout<<d;
}
25.五子棋赢了吗?(简易判断)
题目详情
假设五子棋的棋盘是
N * N
的(正整数N<20
),黑子用*
表示,白子用#
表示,空位置用.
表示。
现给你一个棋局,请判断黑子是否获胜,如获胜,显示Win,并给出获胜排列的最左边那列的最上方那颗棋子的坐标。(棋盘左上角坐标是(0, 0)
,右下角坐标是(N-1, N-1)
)
如果未获胜,则显示“Not yet”。
注意:
- 不考虑白子是否获胜以及棋子个数与黑子是否匹配,只考虑黑子排列。
- 为简化计算,不用考虑“活四”、“四三连”、“长连”、“三三连”等获胜或禁手条件,只判断黑子有5个(或更多)排成一条直线,包括横线、竖线或斜线为胜利条件。
- 输入保证最多只出现一处黑子胜利的排列,不需要考虑有多处排列时如何判断最左位置。
输入格式
第一行是正整数
N(N<20)
,接下来是表示棋盘排列的N
行字符,每行有N
个*
或#
或.
字符。
输出格式
若黑子
(用*表示)
获胜,打印一行字符,依次是Win X Y
,其中X
Y
是黑子获胜排列的最左边那列的最上方的一颗棋子的坐标,X
表示横坐标,Y
表示纵坐标。
若黑子未获胜,打印一行:Not yet
。
输入样例
输出样例
Not yet
代码及解析如下:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s[21];
int n,i,j;
cin>>n;
for(i=0;i<n;i++){
cin>>s[i];
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(s[i][j]=='*'){
//五子棋,j+4不能超出边界,横向判断
if(j+4<n&&s[i][j+1]=='*'&&s[i][j+2]=='*'
&&s[i][j+3]=='*'&&s[i][j+4]=='*')
{
printf("Win %d %d",j,i); //根据题意,这是一个以左上角为原点的坐标系
return 0; //输出的是坐标
}
//竖向判断
if(i+4<n&&s[i+1][j]=='*'&&s[i+2][j]=='*'
&&s[i+3][j]=='*'&&s[i+4][j]=='*')
{
printf("Win %d %d",j,i);
return 0;
}
//斜右下判断
if(i+4<n&&j+4<n&&s[i+1][j+1]=='*'&&s[i+2][j+2]=='*'
&&s[i+3][j+3]=='*'&&s[i+4][j+4]=='*')
{
printf("Win %d %d",j,i);
return 0;
}
//斜左下判断
if(i+4<n&&j-4<n&&s[i+1][j-1]=='*'&&s[i+2][j-2]=='*'
&&s[i+3][j-3]=='*'&&s[i+4][j-4]=='*')
{
printf("Win %d %d",j-4,i+4);
//斜左下,最左边第一颗棋子应该是最下面的一颗
return 0;
}
}
}
}
printf("Not yet");
}
26.莫尔斯码(Morse Code)
题目详情
大家有木有看过带谍战剧?里面多数都有发电报的情节吧,有木有感觉滴滴答答地发报特别酷?
发报的那个东西,学名叫做“电键”,如图:
电键按下去之后,电路接通,就会发出声音,长短不同的声音组合,就形成了不同的编码,可以表示不同的信息~
汉字个数太多,所以汉字的编码是很复杂的。但是英文字母比较少,编码就容易多了
我们今天来研究一种国际通用的电报编码——莫尔斯码。
我们用“滴(Di~)”来模拟电键短按发出的声音,用一个点(dot)表示:.
用“答(Da~)”来模拟电键长按发出的声音,用一个短划(dash)表示:-
英文字母和数字的莫尔斯码是:
- 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 --..
- 0 -----
- 1 .----
- 2 ..---
- 3 ...--
- 4 ....-
- 5 .....
- 6 -....
- 7 --...
- 8 ---..
- 9 ----.
例如求救信号 `SOS` 的莫尔斯码就是: `... --- ...` (每个字母的编码中间空一格)
现在请将输入的编码转成文本、将输入的文本转成编码。
输入格式
第一行为一个正整数
N
,
接下来N
行,每行为不超过200个字符的文本或者编码。
我们把连续的一串字母或数字的组合称之为一个“单词”,输入的文本格式是:每个单词之间空一格,文本的首末两端没有空格,例如CQ CQ
,文本仅有大写字母、数字、空格组成。
输入的编码的格式是:每个单词内的字母编码或数字编码之间空一格,每个单词之间用|
分隔,例如-.-. --.-|-.-. --.-
(文本CQ CQ
的编码)
输出格式
对每一行输入的文本或编码,采用相对应的格式,在一行中对应给出其编码或文本。
输入样例
2
-.-. --.-|-.-. --.-|-.-. --.-|-.. .|-... -.. ..... .... .-.. .-|-... -.. ..... .... .-.. .-|-.-
CQ CQ CQ DE BD5HLA BD5HLA K
输出样例
CQ CQ CQ DE BD5HLA BD5HLA K
-.-. --.-|-.-. --.-|-.-. --.-|-.. .|-... -.. ..... .... .-.. .-|-... -.. ..... .... .-.. .-|-.-
代码节解析如下:
/*容我先吐槽一句:这题巨tm恶心.....*/
#include<stdio.h>
#include<string.h>
//a数组存字母和数字,b数组存所有的莫尔斯码
char a[100]={'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','0','1','2','3','4','5','6','7','8','9'};
char b[100][100]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",
".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....",
"-....","--...","---..","----."};
//将莫尔斯码转为数字字母
void zimu(char c[]){
for(int i=0;i<strlen(c);i++){
char str[5];
int j=0;
//当个莫尔斯码分块没有结束的时候,就把他存起来
while(c[i]!=' '&&c[i]!='\0'&&c[i]!='|'){
str[j++]=c[i++];
}
str[j]='\0';//不要忘了加
for(int k=0;k<36;k++){
if(!strcmp(str,b[k])) //从b数组里找到该莫尔斯码块
printf("%c",a[k]);
}
if(c[i]=='|') //遇到‘|’打印空格
printf(" ");
j=0;
for(int f=0;f<5;f++)
str[f]=0; //每次转化为一个数字后 都初始化一下临时数组
}
}
//将数字字母转化为莫尔斯码
void xiaodiandian(char c[]){
for(int i=0;i<strlen(c);i++){
for(int j=0;j<36;j++){
if(c[i]==a[j]) //从a数组里找到对应的数字或字母
printf("%s",b[j]);
}
if(c[i]==' ') //遇到‘ ’打印‘|’
printf("|");
//单词中的每个字符转化后空一格
if(c[i]!=' '&&c[i+1]!=' '&&i!=strlen(c)-1)
printf(" ");
}
}
int main(){
int n,i;
scanf("%d",&n);
getchar();
char c[n][2000]; //这种声明数组长度的方式要分编译环境
int k=0;
for(i=0;i<n;i++){
gets(c[i]);
//输入的是莫尔斯码
if(c[i][0]=='-'||c[i][0]=='.')
zimu(c[i]);
//输入的是数字
else
xiaodiandian(c[i]);
if(i!=n-1)
printf("\n");
}
return 0;
}
27.部分排序
题目详情
对于一组数据,我们可以只对原先处在中间位置的那些元素进行排序。
输入格式
在一行内输入
n r a1 a2 ... an
其中,不大于200的正整数n
表示该组数据的个数;不大于200的非负整数r
表示该组数据两端各自留有r
个数不参与排序,若r+r>=n
,则该组数据无需排序。
整数a1 a2 ... an
是该组的n
个数据,且都在8位以内。
输出格式
排序之后的序列,元素之间用一个空格间隔,最后一个元素之后不加空格。
输入样例
5 1 6 5 4 3 2
输出样例
6 3 4 5 2
代码及解析如下:
#include <iostream>
using namespace std;
int main(){
int n,r;
cin>>n>>r;
int a[201];
int i,j;
for(i=0;i<n;i++){
cin>>a[i];
}
//不用排序
if(r+r>=n){
for(i=0;i<n;i++){
cout<<a[i];
if(i<n-1)cout<<' ';
}
}
else {
//从r开始排序,排到n-r,用冒泡排序
for(i=r;i<n-r;i++){
for(j=r;j<n-i-1;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
}
}
}
for(i=0;i<n;i++){
cout<<a[i];
if(i<n-1)cout<<' ';
}
}
}
28.刷题与Z老师的头发
题目详情
在Pintia上,每天Z老师出题、小盆友们刷题。Z老师的头发遵从以下规律:
1、每天生长出60根头发;
2、每出一道题,减少20根头发;
3、每天结束时统计累积做题情况:
(1)若出的题全部被做出来,则Z老师产生“没题焦虑”,减少30根头发;
(2)若小盆友做出来的题少于50%,则Z老师产生“学生不用功焦虑”,减少70根头发。
现给定连续N天的出题、刷题情况,请计算Z老师头发的变化情况。
输入格式
第一行输入一个正整数
N
(N<20
);
接下来N
行,每行输入两个非负整数,分别是一天的出题数量q
和刷题(做出来)数量s
,以空格间隔。
题目输入保证出题总数量不超过N*10
,并且每天的刷题量不会使累积刷题数量超过累积出题数量。
输出格式
若Z老师头发增加
K
根,则输出+K
;若Z老师头发减少K
根,则输出-K
;若没有变化,则输出--
输入样例
3
5 3
5 1
5 11
输出样例
-220
代码及解析如下:
#include <stdio.h>
int main(){
int n,a,b,sum1=0,sum2=0;
scanf("%d\n",&n); //n天
int i,toufa=0;
//要把每天Z老师的出题量和学生刷题量累加起来
for(i=0;i<n;i++){
toufa+=60; //每天长60根
scanf("%d %d",&a,&b);
sum1+=a; //sum1为z老师出题总数
sum2+=b; //sum2为学生刷题总数
toufa=toufa-a*20;
if(sum1==sum2){ //全做出来,”没题焦虑“
toufa=toufa-30;
}
else if(1.0*sum2<0.5*sum1){ //学生做出来的少于0.5
toufa=toufa-70;
}
}
if(toufa>0)printf("+%d",toufa);
else if(toufa<0)printf("%d",toufa);
else printf("--");
}
29.百鸡问题扩展-N鸡问题
题目详情
N
元钱买N
只鸡,公鸡每只5元,母鸡每只3元,小鸡1元3只,N
元钱必须刚好买N
只鸡,而且鸡必须整只买,不能劈开买。
有几种买法呢?这就是N鸡问题。
输入格式
在一行中输入一个正整数
N
。(N<500
)
输出格式
在一行中输出两个整数
c
s
,中间用一个空格隔开,表示N
元钱买N
只鸡共有c
种买法,且所有买法的公鸡数量之和是s
。
输入样例
100
输出样例
4 24
代码及解析如下:
注:
//公鸡最贵,要就着公鸡来,其次是母鸡
//公鸡的数量决定母鸡的数量决定小鸡数量
//三种鸡的数量之和为n,三种鸡的价钱总和为n
#include <stdio.h>
#define N 500
int main(){
int n;
scanf("%d",&n);
int gongji,muji,xiaoji; //公鸡,母鸡,小鸡的数量
int count=0;
int i=0,sum=0;
for(gongji=0;gongji<=n/5;gongji++){ //最多能买n/5只公鸡
for(muji=0;muji<=n/3;muji++){
xiaoji=n-gongji-muji; //三种鸡的数量之和为n
if(5*gongji+3*muji+xiaoji/3.0==n){ //三种鸡的价钱总和为n
count++;
sum+=gongji;
break;
}
}
}
if(count){
printf("%d %d",count,sum);
}
else printf("0 -1");
return 0;
}
30.购买火车票
题目详情
我们省略了很多现实中购买火车票的细节,对于一趟列车,根据输入的购票订单信息,查询余票并购票。
座位是复用的,即订某段行程,只在该段行程内占据一个座位,在行程外不占座位。举个🌰 :
某列车有青岛、济南、天津、北京四站(青岛发往北京),有10个座位,则:
(1)订购青岛-天津车票1张,应先显示有余票10张,并执行购票操作;
(2)再订天津-北京车票1张,显示余票10张,并执行购票操作;
(3)再订济南-天津车票9张,显示余票9张,并执行购票操作;
(4)再订青岛-天津车票1张,显示余票0张,并提示不能购票。
为简化,售出的车票是不固定座位的,仅保证“有座位可以坐”。例如:一列仅有2个座位的青岛-济南-北京的列车,
乘客A先订1张青岛-济南车票,可能占据0号座位;
乘客B再订1张济南-北京车票,可能占据1号座位(尽管有一个好像更优化的方案是让B占据0号座位,但此题不需要考虑);
乘客C再订1张青岛-北京的车票,看上去没有青岛-北京的空座位(没有票了),但是他可以在两段行程分别坐在0号和1号座位,所以依然可以成功购票。
输入格式
第一行输入站点数量
N
(N>1
且N<=50
)和座位数量S
(正整数S<=200
),中间空一格。
第二行输入N
个站点名称(名称仅由字母和数字组成,长度不超过30),以空格分隔,车站按照列车运行方向从起点至终点依次排列。
第三行输入订单数量m
(正整数m<=50
)
接下来m行,每行是一个订单,内容依次是上车车站名 下车车站名 订票数量
,中间以空格分隔。
输出格式
对于每个订单,在一行内给出订票结果:先显示该行程的余票,然后打印“YES”或“NO”表示购票成功或购票失败。
输入样例
4 10
Qingdao Jinan Tianjin Beijing
4
Qingdao Tianjin 1
Tianjin Beijing 1
Jinan Tianjin 9
Qingdao Tianjin 1
输出样例
10 YES
10 YES
9 YES
0 NO
代码及解析如下:
#include <iostream>
#include <map>
using namespace std;
const int N=210;
string zhandian[N]; //站点存到字符串数组
int zuowei[N]; //表示当前站点有几个座位
int main()
{
map<string,int>a;
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>zhandian[i];
a[zhandian[i]]=i; //将每个站点出现的下标存下来
}
for(int i=0;i<n;i++)
{
zuowei[i]=m; //每个座位初识m个座位
}
int q;
cin>>q; //q个询问
while(q--)
{
string s1,s2;
int ticket;
cin>>s1>>s2>>ticket;
int begin=a[s1];
int end=a[s2];
int min=10000;
for(int i=begin;i<end;i++)
{
if(min>zuowei[i])
{
min=zuowei[i];
}
}
//从始站点到终站点,找到票数最少的时候,
//如果票数最少的时候能满足客户那从始终站点就能满足
if(min>=ticket)
{
cout<<min<<" "<<"YES"<<endl;
//中途有票被买,座位数-1
for(int i=begin;i<end;i++)
{
zuowei[i]-=ticket;
}
}
else cout<<"0 NO"<<endl;
}
}
注: 本栏目所有的题目均来自于学校程序设计课程的平时作业,如果对您有帮助的话,请点赞加关注,有任何不理解的地方也可以在评论区中留言或者私信我哦!
码文不易,还请多多支持~~