D题 火车购票
先来个错误示范,75分代码:
#include <bits/stdc++.h>
using namespace std;
int n,cnt,tmps,rest[110],vis[110];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=20;i++)
rest[i]=5;//每排剩余5张票
for(int i=1;i<=n;i++)
{
cin>>cnt;
for(int j=1;j<=20;j++)//第j排
{
if(rest[j]>=cnt)//第j排剩余的票数大于等于cnt,则可以让cnt个座位相邻
{
tmps=0;//记录出票数
for(int k=(j-1)*5+1;k<=j*5;k++)//遍历第j排座位,k为座位编号
{
if(vis[k]==0)//第k个座位还未被购买
{
vis[k]=1;
tmps++;
if(tmps<cnt)
printf("%d ",k);
else if(tmps==cnt)//已经出了cnt张票了,结束
{printf("%d\n",k);rest[j]=rest[j]-cnt;break;}
}
}
break;
}
}
}
return 0;
}
为什么只得75分呢?
因为没考虑这种情况:当前要购买的票数大于每一排剩余的票数,这样无法保证出票的是同一排的相邻座位。举个例子,现在每一排都只剩了3个座位,而要一次购买5张票,那么只能第一排出2张票,第二排出3张票,这五张票不是都相邻的。
100分 AC代码:
#include <bits/stdc++.h>
using namespace std;
int n,cnt,tmps,flag,rest[110],vis[110];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=20;i++)
rest[i]=5;//每排剩余5张票
for(int i=1;i<=n;i++)
{
cin>>cnt;
flag=0;
for(int j=1;j<=20;j++)//第j排
{
if(rest[j]>=cnt)//第j排剩余的票数大于等于cnt,则可以让cnt个座位相邻
{
flag=1;//标记:可以做到cnt个座位相邻
tmps=0;//记录出票数
for(int k=(j-1)*5+1;k<=j*5;k++)//遍历第j排座位,k为座位编号
{
if(vis[k]==0)//第k个座位还未被购买
{
vis[k]=1;
tmps++;
if(tmps<cnt)
printf("%d ",k);
else if(tmps==cnt)//已经出了cnt张票了,结束
{printf("%d\n",k);rest[j]=rest[j]-cnt;break;}
}
}
break;
}
}
if(flag==0)//无法做到cnt个座位相邻
{
tmps=0;
for(int i=1;i<=100;i++)
{
if(vis[i]==0)
{
vis[i]=1;
tmps++;
rest[(i-1)/5+1]--;
if(tmps<cnt)
printf("%d ",i);
else if(tmps==cnt)
{printf("%d\n",i);break;}
}
}
}
}
return 0;
}
B题 公共钥匙盒
这题说实话,有点难度啊…
看了一下网上其他人写的题解,是写了结构体的多维排序。我的思路是遍历所有时刻,如果现在遍历的时刻有放回或取出就按题目要求进行操作。仔细想了一下,时间复杂度是O(n*n*s),极限数据可以到1e10了,竟然也给我AC了?好吧,我也只想到了暴力模拟…
如果想看多维排序解题的,可以看看这篇文章:https://blog.csdn.net/L_xqqzldh/article/details/87938066
假的100分 AC代码:
#include <bits/stdc++.h>
using namespace std;
bool vis[1010],is_out[10110],is_in[10110];
vector<int>out[10110],in[10110];
int n,m,mx,t1,t2,d,num,a[1010];
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++)
a[i]=i;
for(int i=1;i<=m;i++)
{
cin>>num>>t1>>d;
t2=t1+d;
out[t1].push_back(num);//保存t1时刻取出钥匙的编号(可能取出多个)
in[t2].push_back(num);//保存t2时刻放回钥匙的编号(可能放回多个)
is_out[t1]=1;//t1时刻有取出
is_in[t2]=1;//t2时刻有放回
mx=max(mx,t2);//mx为最大时刻
}
memset(vis,1,sizeof(vis));//开始时所有挂钩均被占用
for(int i=1;i<=mx;i++)//遍历所有时刻
{
if(is_in[i]==1)//i时刻有放回(先全部放回再取出)
{
sort(in[i].begin(),in[i].end());//放回时要按从小到大放回
for(int j=0;j<in[i].size();j++)
{
for(int k=1;k<=n;k++)
{
if(vis[k]==0)//第k个挂钩没被占用
{
a[k]=in[i][j];//in[i][j]表示i时刻放回的第j把钥匙的编号
vis[k]=1;
break;
}
}
}
}
if(is_out[i]==1)//i时刻有取出
{
for(int j=0;j<out[i].size();j++)
{
for(int k=1;k<=n;k++)
{
if(a[k]==out[i][j])//out[i][j]表示i时刻取出的第j把钥匙的编号,找到了编号为out[i][j]的钥匙,将其取出
{vis[k]=0;break;}
}
}
}
}
for(int i=1;i<=n;i++)
i==n?printf("%d\n",a[i]):printf("%d ",a[i]);
return 0;
}
A题 打酱油
100分 AC代码:
#include <bits/stdc++.h>
using namespace std;
int n,s,t1,t2,t3,ans;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
s=n/10;
t1=s/5;
t2=(s-t1*5)/3;
t3=s-t1*5-t2*3;
ans=7*t1+4*t2+t3;
printf("%d\n",ans);
return 0;
}
C题 最大波动
100分 AC代码:
#include <bits/stdc++.h>
using namespace std;
int n,mx,a[1010];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
mx=0;
for(int i=2;i<=n;i++)
mx=max(mx,abs(a[i]-a[i-1]));
printf("%d\n",mx);
return 0;
}