题目大意:总长度为n的路径上有m个点,主角在从1走到n的过程中需要饼干。规则如下,(1)走到m个点的任意一个点都必须吃饼干,(2)每次行走距离达到d时必须吃饼干,吃完饼干后行走距离归零。要求:(1)计算出主角吃饼干的总数(注意可以删除一个点再计算总数)(2)如果可以删除一个点,哪么可以删除的点的数量。
初步分析:有两种情况,一是可以删除某个点使得次数少一个(需要统计这些点数量),另一种就是删除任何一个点总数都不变(注意这种情况可以看成删除点数量为m)。
解题方法:模拟法。什么是模拟法?如果问人这个问题,你怎么知道删除这个点会不会减少次数呢?哪么你肯定会在草稿纸上算一下。把这个过程不加改变地用在程序中,这是我理解的模拟法。
因为只能删除一个点,可以在计算总数过程中,顺路进行枚举,例如判断a[i]能否删除,计算下吃饼干次数t1+t2和t3的大小可知。具体细节看代码注释。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int n,m,d,t,i,j,a[100005]= {1},t1,t2,t3;
cin>>t;
while(t--)
{
int sum=1,cnt=0;/**< sum统计次数,cnt统计可以拿走某一个的次数 */
cin>>n>>m>>d;
for(i=1; i<=m; i++)
cin>>a[i];
a[m+1]=n;
for(i=1; i<=m; i++)/**<模拟删除某个a[i]会不会使得整个次数减少一次 */
{/**< t1,t2,t3,分别用于统计次数 */
if((a[i]-a[i-1])%d)
t1=(a[i]-a[i-1])/d+1;
else
t1=(a[i]-a[i-1])/d;
if(i<m&&(a[i+1]-a[i])%d)
t2=(a[i+1]-a[i])/d+1;
else
t2=(a[i+1]-a[i])/d;
if(i<m&&(a[i+1]-a[i-1])%d)
t3=(a[i+1]-a[i-1])/d+1;
else
t3=(a[i+1]-a[i-1])/d;
sum+=t1;/**< 统计不删除结点的次数 */
if(t1+t2>t3)/**< 如果拿掉a[i]的次数t3小 */
cnt++;
}
sum+=(n-a[m])/d;/**< 最后走到n */
if(cnt>0)/**< 如果可以删除某些结点,哪么总数减少一次 */
sum--;
if(cnt==0)/**< 无法减少次数,那么拿走m的任何一个都可以 */
cnt=m;
cout<<sum<<' '<<cnt<<endl;
}
return 0;
}