3335: 小杰翻书
题目描述
小杰正在读一本电子书。 该书的文件由n页组成,编号从1到n。 屏幕当前显示页面x的内容,小杰想要读取页面y。 书上有两个按钮,允许小杰向前或向后滚动d页(但他不能在书外滚动)。 例如,如果书由10页组成,并且d = 3,那么从第一页开始,小杰可以通过按下其中一个按钮滚动到第一页或第四页; 同理从第二页可以到第一页或第五页; 从第六页到第三页或第九页; 从第八到第五页或第十页。
帮助小杰计算按下按钮移动到第y页所需的最少次数。
输入
输入一个整数 t (1≤t≤103),代表样例数目
每一个样例有四个整数 n, x, y, d (1≤n,d≤109, 1≤x,y≤n) ,中间用空格分开,分别表示电子书的总页数,当前页数,要到达的页数,每次滚动的页数
输出
如果小杰能够从x页翻到y页的话,就输出最少按动按钮次数,否则输出-1
样例输入
copy
3 10 4 5 2 5 1 3 4 20 4 19 3
样例输出
4 -1 5
提示
第一个样例的页面滚动次序是 :4→2→1→3→5.所以需要按动4次
第二个页面是不能够到达第5页的;所以输出-1;
第三个样例的页面滚动次序是: 4→7→10→13→16→19.,所以需要按动5次
来源
来自准大三老学长的盲目自信 没仔细看数据规模 觉得石锤bfs剪枝优化
结果导致一下午疯狂 T T完又内存超限
还是数学解法好啊。。。
乱七八糟错误代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <memory>
#include <cstdlib>
#include <cstring>
using namespace std;
int dr[2] = {-1, 1};
typedef struct b{
int page;
int step;
} bb;
int bfs(int n,int x,int y,int d)
{
int s[100000];
memset(s,0,sizeof(s));
bb temp;
temp.page = x;
temp.step = 0;
queue<bb> q;
q.push(temp);
//s[x] = 1;
while(!q.empty()){
bb t = q.front();
q.pop();
s[t.page] = 1;
if(t.page == y){
return t.step;
}
for(int i=0;i<=1;i++){
int next = t.page + dr[i]*d;
if(next<1){
next = 1;
}
if(next>n){
next = n;
}
bb n;
n.page = next;
n.step = t.step + 1;
if(s[n.page]==0){
q.push(n);
}
}
}
return -1;
}
int main()
{
int t;
cin>>t;
int n,x,y,d;
while(t--){
cin>>n>>x>>y>>d;
cout<<bfs(n,x,y,d)<<endl;
}
return 0;
}
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int bfs(double n, double x, double y, double d)
{
int yy = (y-x);
if(abs(yy)%(int)d==0){ //直接到达
return abs((y-x)/d);
}
else if((int)(y-1)%(int)d==0&&(int)(n-y)%(int)d!=0){ //左边到达
return ceil(x/d) + (y-1)/d;
}
else if((int)(y-1)%(int)d!=0&&(int)(n-y)%(int)d==0){ //右边到达
//cout<<ceil((n-x)/d)<<endl;
return ceil((n-x)/d) + (n-y)/d;
}
else if((int)(y-1)%(int)d==0&&(int)(n-y)%(int)d==0){ //都能到达
return min((ceil(x/d) + (y-1)/d), (ceil((n-x)/d) + (n-y)/d));
}
return -1;
}
int main()
{
int t;
cin>>t;
double n,x,y,d;
while(t--){
cin>>n>>x>>y>>d;
cout<<bfs(n,x,y,d)<<endl;
}
return 0;
}