有一个磁盘请求序列给出了程序的I/O对各个柱面上数据块请求的顺序,例如一个请求序列为98,183,37,122,14,124,65,67,n=8,请求编号为1-n。如果磁头开始位于位置C(假设不在任何请求的位置,例如C=53)。最短寻道时间优先是一种移动磁头柱面数较小的调度算法(优先处理离磁头最近的请求)。编写一个程序采用最短寻道时间优先算法输出给定的磁盘请求序列的调度方案和磁头移动总数。
输入格式:
第一行有输入1个整数n,表示请求序列个数。 依次输入n行,每行两个数,第一个数为请求编号,从1开始编号,第二个数为磁头位置。 最后一行输入磁头开始位置C。
输出格式:
输出磁头移动总数。
输入样例:
8
1 98
2 183
3 37
4 122
5 14
6 124
7 65
8 67
53
结尾无空行
输出样例:
236
结尾无空行
首先,,这个题目初始判断还是很好理解的,思路也很清晰
1,把磁盘的头部丢进去暴力排序一遍,然后让他左右找差值小的那一个贪心,
2,把贪心过的元素全部赋值为-1打好标记;
3,考虑边界情况。
输出答案即可。。
附上 测试小数据
in
8
1 14
2 34
3 40
4 41
5 42
6 43
7 44
8 45
39
out
37
以及这里面的基本操作手写,后面没打完,,不太想调试了,大家可以尝试看一看原理
可是,让我没有想到的是,这种感觉比较水的题目,硬是写了我两个小时,代码基本功还是很佛,一点都不扎实,主要是调试边界值时容易出错。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <math.h>
#include <algorithm>
using namespace std;
int a[100000];
int ans=0,mark=0,flag=0,k=0;
int n,left_,right_;
void find(int l,int r,int now) { // 开始比较
if (a[now]-a[l] < a[r]-a[now]) { //首先,得判断大小的问题
if (a[l] == -2) { //第二,得判断边界值,如果到了边界。我们就换一边贪心,且只能换一边贪心;
ans+=a[r]-a[now];
k = a[r]; //向右边贪心
mark++;
a[now] = -1;
} else {
ans+=a[now]-a[l];
k = a[l]; //向左边贪心
mark++;
a[now] = -1;
}
} else if (a[r] == -2) {
ans+=a[now]-a[l]; //向左边贪心
k = a[l];
mark++;
a[now] = -1;
} else {
ans+=a[r]-a[now]; //向右边贪心,
k = a[r];
mark++;
a[now] = -1;
}
}
void change(int www) {
for (int i=www-1; i>=0; i--) {
if (a[i] != -1) {
left_ = i;
} //找到第一个不为-1的,且在他左边的数,记录更改left
break;
}
for (int i=www+1; i<=n+2; i++) {
if (a[i] != -1) {
right_ = i; //同理,改变右边;
}
break;
}
}
int main() {
scanf("%d",&n);
memset(a,-1,sizeof(a)); //数组初始化,里面的元素全为-1;
for (int i=1; i<=n; i++) {
scanf("%d%d",&k,&a[i]);
}
scanf("%d",&a[n+1]);
k = a[n+1]; //丢进去磁盘开始的地方
sort(a+1,a+n+2); //排序
int i=0;
a[0] = -2; //边界之外赋值
a[n+2] = -2;
while (1) {
if (mark == n) { //如果我们的标记值为已经达到了n,我们就退出循环,
break;
}
i++; //遍历开始
if (k == a[i]) { //如果找到目前k在元素中的那个地方
change(i); //找到他的左右不为-1的元素下标;
find(left_,right_,i); //比较的状态;
i=0; //因为k的值更新了,所以要从头开始找;
}
}
printf("%d",ans);
return 0;
}
emmm,怎么说呢,是百度了之后发现网上没有一篇适合新手上路的写这道题的题解,我就自己写了一下,有点丑了,c++感觉看不懂的话可以私聊我要c的,这些都差不多,
感觉还是代码不够精简,下次改进叭。