解题思路:
1.是一道纯模拟题,我们只需要建立一个结构体二维数组即可,结构体中包含两个变量,一个bool flag是否有楼梯,一个是int num表示这个房间号的指示牌数字
2.输入数据后,设置一个书签temp,用来表示当前房间号,然后逐层遍历,加上本层的指示牌数字,sum=sum+a[i][temp].num,在i层要找够a[i][temp].num个楼梯房间后,结束循环,跳到上一层
3.注意在书签移动的过程中约瑟夫问题,形成环状
#include<bits/stdc++.h>
using namespace std;
struct node{
bool flag;
int num;
}a[10010][110];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<=m-1;j++)
{
cin>>a[i][j].flag>>a[i][j].num;
}//将每层每个房间的flag和num输入
int temp;
cin>>temp;
long long sum=0;//统计总指示牌的数字
for(int i=1;i<=n;i++)
{
sum=sum+a[i][temp].num;//累加每层指示牌的数字
int ans=a[i][temp].num;//记录本层需要走的楼梯
int x=a[i][temp].flag;//定义本层楼梯的累加器
while(1)
{
if(x>=ans)//如果遍历的有楼梯的房间大于等于ans
break;
temp++;
if(temp>m-1)
temp=0;//如果超出房间号,回到0号房间
x=x+a[i][temp].flag;
}
}
cout<<sum%20123;
return 0;
}
优化思路:
1.这样我们能拿50分,可以想一下,哪里没有通过呢,有一部分为,如果指示牌的数字过大,即使我们开long long 最后的结果也存储不下,那么就需要在每层加上指示牌的时候,就对20123取模,这样解决了数据溢出问题
2.还有一个超时的问题,当x很大的时候,每层的房间只有m个,是小于100的,那么肯定在约瑟夫问题中,做了很多周期性的无效循环,这部分时间是完全耗掉的,那么怎么处理呢?在刚开始输入的时候,就可以将每层的楼梯房数量都统计下来,这样,利用指示牌数字%本层的楼梯房,即应该走的房间,现在解决最后一个问题,取模的结果是可能为0的,比如当本层共有2个楼梯房,指示牌数字 为382,很明显结果为0,但是不可能不走的,最少要走一个周期,所以加上一个判断,如果结果为0,那么该走的房间=本层的楼梯房数量
#include<bits/stdc++.h>
using namespace std;
struct node{
bool flag;
int num;
}a[10010][110];
int b[10010];//统计每层共有多少个楼梯房
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=0;j<=m-1;j++)
{
cin>>a[i][j].flag>>a[i][j].num;
b[i]=b[i]+a[i][j].flag;//统计每层共有多少楼梯房
}//将每层每个房间的flag和num输入
int temp;
cin>>temp;
long long sum=0;//统计总指示牌的数字
for(int i=1;i<=n;i++)
{
sum=(sum+a[i][temp].num)%20123;//累加每层指示牌的数字
int ans=(a[i][temp].num)%b[i];//记录本层需要走的楼梯
if(ans==0)//如果需要走的楼梯为0,即走了正好重复的圈数
ans=b[i];//因为不可能是0,那么就让他走一圈
int x=a[i][temp].flag;//定义本层楼梯的累加器
while(1)
{
if(x>=ans)//如果遍历的有楼梯的房间大于等于ans
break;
temp++;
if(temp>m-1)
temp=0;//如果超出房间号,回到0号房间
x=x+a[i][temp].flag;
}
}
cout<<sum;
return 0;
}