题解 P1166 【打保龄球】
题目传送门
明显的模拟题,但不过坑点挺多的,而且光题意就理解的够呛。
那么我先来概括一下题意:
首先你一共可以投一局,一局里可以分成十轮(但不过有时候会多出来一到两轮,这种情况等一下再讲),在一局中,一共有十个柱,会出现很多种情况。
第一种:如果你第一次就把十个给打倒了,那么这一局直接结束,而这一局的分数=10+后两次滚球的得分(若是第十轮则还需另加两次滚球);
第二种:如果第一次没全部打倒,第二次把剩下的全部打倒,这一局也直接结束,那么这一局的得分=10+后一次滚球的得分(若是第十轮则还需另加一次滚球);
第三种:如果前两次都没能全部打倒,那么这一局得分=这两次滚球的打倒数量。
最后需要求出每一局的得分,和前i局的总得分
总结一下:就是每一局都要打完十个柱,如果两次都打不完那么这局结束,再根据规则得分。
排坑:
讲完了题意感觉还挺简单,但稍不注意会掉到坑里,比方说题目中有这小小的一行字:
“若某轮的得分暂时无法算出,则该轮得分不显示”
那么得分无法算出是什么意思呢?
那自然就是这局还没滚完,但没有数据了,那么显然后面的几局也是没滚完的,所以直接break。
我的思路
(写出来居然要比楼上的大佬短):
1.(读入啊什么的就不说了,自己注意一下空格就好);
2.我先用rest记录剩余柱的数量,再用flag记录是否全部打完,flag=1表示未全部打倒,反之则全部打倒,然后我们在记录一个变量st表示这一局的起点;
3.从st~st+2模拟,该-的-,该+的+,同时判断枚举时是否越界,如果越界了那么直接break,如果当rest=0时,说明全部打倒,那么flag=0,如果枚举到了第三次滚球,而且没有全部打倒即flag=0,那么这次滚球就不做,做完一局后,改变st的位置,如果第一次就全部打完那么st+1,否则st+2。
这样就能避免掉坑了。
最后附上香喷喷的代码
#include<bits/stdc++.h>
using namespace std;
#define mid (l+r)/2
#define ll long long
#define For(i,j,k) for(int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
inline ll read(){
ll x=0;char ch=getchar();bool f=0;
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return f?-x:x;
}
void write(ll x){
if(x<0) putchar('-'),x=-x;
if(x>=10) write(x/10);putchar(x%10+'0');
}
void writeln(ll x){write(x);puts("");}
void writep(ll x){write(x);putchar(' ');}
int n,cnt,ans,sum[13];
char a[103];
int main()
{
while (cin>>a[++n]);//读入
int st=1;//每一局的起点
for (int i=1;i<=10;i++){
int rest=10,flag=1;//剩余rest根柱,且没有全部打完
for (int j=st;j<=st+2;j++){//枚举三次滚球
if (j>n){//如果越界退出
sum[i]=-1;
break;
}
if (rest==0) rest=10,flag=0;//全部打完
if (j==st+2 && flag) break;//第三种情况,只滚两次
if (a[j]=='/') sum[i]+=rest,rest=0;//模拟
else if (a[j]>='0' && a[j]<='9') sum[i]+=a[j]-'0',rest-=a[j]-'0';//模拟
}
if (sum[i]==-1) break;//越界
if (a[st]=='/') st++;
else st+=2;//改变st位置
writep(sum[i]);
}
puts("");
for (int i=1;i<=10;i++){
if (sum[i]==-1) break;
ans+=sum[i];
writep(ans);
}
return 0;
}
码字不易,希望对您有用