第二周^_^
第一题
26个大写字母里面,有一部分字母是带有圈的,比如A有1个圈,B有2个圈,C没有圈,
给你一个带有n个大写字母组成的字符串,请问一共有多少个圈圈。
你可以将字母中完全封闭的一个区域当作一个圈。
输入描述:
第一行输入一个整数t,代表有t组测试数据,
对于每组测试数据,
第一行输入一个整数n代表字符串的长度,
第二行输入一个长度为n的字符串S,保证只由大写字母组成。
1<=t<=10
1<=n<=1*10^5
输出描述:
对于每组测试数据,输出一个整数代表这个字符串共有多少个圈圈。
并且对于每组数据,答案占单独的一行。
示例
输入:
2
8
HELLOACM
16
XINSHENGSAIJIAYOU
输出:
2
3
#include<stdio.h>
int main()
{
int t,n,i,j,quan=0;
scanf("%d",&t);
int num[t];
for(i=0;i<t;i++)//26个字母中B有两个圈圈,ADOPQR有一个圈圈,其余的字母无圈圈
{
scanf("%d",&n);
getchar();
char str[100000];
gets(str);//将字符串输入一个数组
for(j=0;j<n;j++)//遍历数组,看每一个字母的圈圈数并累加
{
if(str[j]=='B')//判断是否有两个圈
{
quan+=2;
}
else if(str[j]=='A'||str[j]=='D'||str[j]=='O'||str[j]=='P'||str[j]=='Q'||str[j]=='R')//判断是否有一个圈
{
quan+=1;
}
}
num[i]=quan;//将该字符串圈圈数存入num数组便于后面统一输出
quan=0;
}
for(i=0;i<t;i++)//输出各字符串圈圈数
{
printf("%d\n",num[i]);
}
return 0;
}
总结:
该题中,26个英文字母带有圈圈的只有7个,使用简单的判断语句即可求得字符串中的圈圈总数。我在做题时的难点在于每次循环如何重置字符数组来存入本次循环所要用到的字符串。
我的解决方案是直接在循环里面定义一个字符数组,这样每次循环时字符数组都会被重新定义一次,但出现了问题-_-#。
for()
{…
char str[n];
…
}
以上是我最先定义数组的方式,通过要输入字符串的字母数量来定义数组的大小,但输出结果出错。
就题目所给数据为例,第二个字符串结果依然正确,但第一个字符串的圈圈数由2变成了81。将char str[n]改为char str[100000]后程序输出结果正确。
第二题
由于两个同学学习了很久,想要打牌放松一下,但是他们两个眼睛有点花了,看不清牌的花色,只看得清牌的点数。所以他们改良了一了规则。
规则如下:
1.不分花色,只有牌的点数(2-10)
2.每个人三张牌,一共有4种牌型,按牌型大小排序如下:
(1)三同:三张牌点数相同,如6 6 6,8 8 8
(2)顺子:三张牌点数连续,如3 4 5,5 6 7
(3)对子:两张牌点数相同,另一张不同,如2 3 3,7 7 8
(4)单牌:三张牌点数都不同,且不连续,如2 3 5,9 4 7
3.牌型不同则牌型大的赢,否则按如下规则比较:
(1)三同:直接比较大小,如果相同则平局
(2)顺子:比较最大点数的大小,如果相同则平局
(3)对子:比较对子的大小,如果相同比较单牌的大小,如果都相同则平局
(4)单牌:先比较最大的牌,如果相同比较第二大的牌,如果相同则比较最小的牌,如果都相同则平局
你作为裁判需要判断谁是胜利者。
输入描述:
第一行输入一个整数t,代表有t组测试数据,
对于每组测试数据,
输入连续6个整数,a,b,c,d,e,f,其中a,b,c代表benTuTuT的牌,其中d,e,f代表XXL的牌
1<=t<=1000
2<=a,b,c,d,e,f<=10
输出描述:
对于每组测试数据,如果benTuTuT胜利则输出"benTuTuT win!",如果XXL胜利则输出"XXL win!",否则输出"No winner!"
并且对于每组数据,答案占单独的一行。
PS:请输出双引号内的所有内容,并且请勿输出双引号!
示例
输入:
7
2 3 4 3 4 5
3 3 3 6 6 6
2 3 5 2 3 6
2 2 3 2 2 4
10 10 9 2 3 4
2 2 2 8 9 10
7 7 7 7 7 7
输出:
XXL win!
XXL win!
XXL win!
XXL win!
XXL win!
benTuTuT win!
No winner!
# include<stdio.h>
int pai(int num[])//pai函数用于将玩家抽到的三张牌按点数由小到大排列。
{
int i,j,temp;
for(i=0;i<2;i++)
{
for(j=0;j<2-i;j++)
{
if(num[j]>num[j+1])
{
temp=num[j];
num[j]=num[j+1];
num[j+1]=temp;
}
}
}
}
int pan(int x,int num[],int y[])//pan函数是评分系统,将给每种不同的牌型赋分,其中三同为4分,顺子为3分,对子为2分,单牌为1分。然后比较两位玩家的分值,分值大的玩家直接胜出。
{ //当分值相同时则说明两位玩家的牌型相同,之后再具体比较。
int i;
for(i=0;i<2;i++)//将y1和y2数组初始化为零。
{
y[i]=0;
}
if(num[0]==num[1]&&num[1]==num[2])//分数判定
{
x+=4;
}
else if(num[0]-num[1]==-1&&num[1]-num[2]==-1)
{
x+=3;
}
else if(num[0]==num[1])
{
x+=2;
y[0]=num[0];
y[1]=num[2];
}
else if(num[0]==num[2])
{
x+=2;
y[0]=num[0];
y[1]=num[1];
}
else if(num[1]==num[2])
{
x+=2;
y[0]=num[1];
y[1]=num[0];
}
else
{
x+=1;
}
return x;
}
int main()
{
int t,i,j,x1,x2,y1[2],y2[2];//x1和x2分别为两位玩家的每一局得分情况。
int num1[3],num2[3]; //y1与y2两个数组用于记录当玩家牌型为对子时的相等的两张牌的大小和与另外两张牌不同的那张牌的大小。
scanf("%d",&t); //如牌为2 3 2,则y1[0]=2,y2[1]=3。
int win[t]; //num1和num2数组用于存储两位玩家每一局抽到的牌。
for(i=0;i<t;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&num1[j]);
}
for(j=0;j<3;j++)
{
scanf("%d",&num2[j]);
}
pai(num1);//将抽到的牌排序。
pai(num2);
x1=0;//初始化两位玩家的分数为0。
x2=0;
x1=pan(x1,num1,y1);//计算分数。
x2=pan(x2,num2,y2);
if(x1>x2)
{
win[i]=1;//win数组用于记录每一局的胜负情况,1则是benTuTuT win!,2则是XXL win!,0则是No winner!。
}
else if(x1<x2)
{
win[i]=2;
}
else if(x1==x2)
{
if(y1[0]==0&&y1[1]==0&&y2[0]==0&&y2[1]==0)
{
if(num1[2]>num2[2])
{
win[i]=1;
}
else if(num1[2]<num2[2])
{
win[i]=2;
}
else if(num1[1]>num2[1])
{
win[i]=1;
}
else if(num1[1]<num2[1])
{
win[i]=2;
}
else if(num1[0]>num2[0])
{
win[i]=1;
}
else if(num1[0]<num2[0])
{
win[i]=2;
}
else
{
win[i]=0;
}
}
else if(y1[0]>y2[0])
{
win[i]=1;
}
else if(y1[0]<y2[0])
{
win[i]=2;
}
else if(y1[1]>y2[1])
{
win[i]=1;
}
else if(y1[1]<y2[1])
{
win[i]=2;
}
else
{
win[i]=0;
}
}
}
for(i=0;i<t;i++)//输出胜负情况
{
if(win[i]==1)
{
printf("benTuTuT win!\n");
}
else if(win[i]==2)
{
printf("XXL win!\n");
}
else
{
printf("No winner!\n");
}
}
return 0;
}
总结:
该题题目信息量较大,判断输赢的条件较多。最开始我打算直接使用if判断语句判断输赢,但发现条件过多,导致代码中嵌入的if式语句较多,写到最后我自己都难以理清代码逻辑,修改困难。
最终,我决定将不同的的牌型量化为相应分数,通过直接比较不同牌型的分数大小从而直接判断出输赢,而分数相等则刚好说明两人牌型相同,再进行相应判断。
这样可以减小代码的复杂性,提高可读性,让我只需注意两人牌型相同时的判断即可。
选做题:
给定n个数字,你需要从中选出一些连续的数字,让这些数的和尽量大。
但是选出的数必须都大于等于x,小于等于y,且这些数不能超过z个
输入描述:
第一行输入一个整数t,代表有t组测试数据,
对于每组测试数据,
第一行输入4个整数n,x,y,z,意义如题所示
第二行输入空格隔开n个数a[i],表示连续的n个数
1<=t<=10
1<=n<=1*10^5
1<=x<=y<=1*10^9
1<=z<=n
1<=a[i]<=1*10^9
输出描述:
对于每组测试数据,输出一个整数代表能得到的最大和是多少
并且对于每组数据,答案占单独的一行。
示例
输入:
1
10 2 6 3
2 7 2 3 3 3 1 3 5 7
输出:
9
#include<stdio.h>
int main()
{
int t,n,x,y,z;
scanf("%d",&t);// 输入t
int i,j,k,sum=0,sumx[t];//sum用来存储3个连续数字的和,sumx数组用来存储每组测试数据的最大和
for(i=0;i<t;i++)
{
sumx[i]=0;//初始化每一组测试数据的最大和为零
scanf("%d %d %d %d",&n,&x,&y,&z);
int a[n];
for(j=0;j<n;j++)
{
scanf("%d",&a[j]);//存入测试数据
}
for(j=0;j<n;j++)//用z个连续数字的第一个数作为计算起点,通过循环不断求出测试数据中连续z个数的和
{
for(k=j;k<j+z;k++)//限制求和在连续的z个数的条件下
{
if(a[k]>=x&&a[k]<=y)//检查这连续的z个数是否满足大于等于x小于等于y的条件
{
sum+=a[k];//满足则累加求和
}
else
{
break;//不满足则结束这z个数的求和过程
}
}
if(sum>sumx[i])//将满足条件的z个数的和与上一次求得的和相比较,让最大和存入sumx数组作为该组测试数据的最大和
{
sumx[i]=sum;
}
sum=0;//sum归零,为下一次循环计算做准备
}
}
for(i=0;i<t;i++)//输出每组测试数据的最大和
{
printf("%d\n",sumx[i]);
}
return 0;
}
总结:
该题我使用了多个循环结构,在输入的数组上连续求多个连续数字的和,当连续数字中有数字不符合条件时就整体向前推进一位,纳入下一位数字,吐出最前位的不符合条件的数字,并将该连续三位数字的和与前三位连续数字的和相比较,保证每次将最大的和存入sumx数组内。