Car
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
Problem Description
Ruins is driving a car to participating in a programming contest. As on a very tight schedule, he will drive the car without any slow down, so the speed of the car is non-decrease real number.
Of course, his speeding caught the attention of the traffic police. Police record N positions of Ruins without time mark, the only thing they know is every position is recorded at an integer time point and Ruins started at 0.
Now they want to know the minimum time that Ruins used to pass the last position.
Input
First line contains an integer T, which indicates the number of test cases.
Every test case begins with an integers N, which is the number of the recorded positions.
The second line contains N numbers a1, a2, ⋯, aN, indicating the recorded positions.
Limits
1≤T≤100
1≤N≤105
0< ai≤109
ai< ai+1
Output
For every test case, you should output ‘Case #x: y’, where x indicates the case number and counts from 1 and y is the minimum time.
Sample Input
1
3
6 11 21
Sample Output
Case #1: 4
题意:
Ruins 的速度是非递减的,每次警察都是在某一整秒的时间记录Ruins 的位置。问从0开始最少需要多少秒到达最后记录的位置。
分析:
记每两个记录之间的距离为b[i],那么从后往前处理,用sp记录当前的最大速度,为了使时间最短,当b[i]<=sp 我们用一秒开过,当b[i] > sp 时 我们用 t=b[i]/sp +1秒开过,并且最佳的状态是匀速开过,所以sp = b[i]/t;
思路是对的,但是由于题目说的是实数,所以我用先整除在乘的方法判断是否是倍数的处理方法因为精度可能会出问题,而一直WA。。。。
所以最后直接换成了用二分来查找均分的段数。
表示要多打代码啊。。和会长同事想都相同的思路,结果会长一遍过,我WA了。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
double a[maxn],b[maxn];
int main()
{
int t,n,kase=1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
a[0] = 0;
for(int i=n;i>=1;i--)
b[i] = a[i]-a[i-1];
double sp = b[n];
int ans = 1;
for(int i=n-1;i>=1;i--)
{
if(b[i] <= sp)
{
ans++;
sp = b[i];
}
else
{
int l=1,r=b[i]+1,mid;
while(l<=r)
{
mid = (l+r)/2;
if(b[i]/mid>sp) l = mid+1;
else r=mid-1;
}
ans += l;
sp = b[i]/l;
}
}
printf("Case #%d: %d\n",kase++,ans);
}
return 0;
}
附上之前思路的代码;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
double a[maxn],b[maxn];
int main()
{
int t,n,kase=1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
a[0] = 0;
for(int i=n;i>=1;i--)
b[i] = a[i]-a[i-1];
double sp = b[n];
int ans = 1;
for(int i=n-1;i>=1;i--)
{
if(b[i] <= sp)
{
ans++;
sp = b[i];
}
else
{
int t = b[i]/sp;//精度有问题,到后面无法满足t*sp == b[i],导致一直都要多分一份
if(t*sp == b[i])
{
ans += t;
sp = b[i]/(t*1.0);
}
else
{
t++;
ans += t;
sp = b[i]/(t*1.0);
}
}
}
printf("Case #%d: %d\n",kase++,ans);
}
return 0;
}