Problem
Description
Input
Output
Sample Input
4 2
1 2 2
2 0 2
3 0 0
4 2 0
Sample Output
1 2 1
Hint
圆圈只在出现的时刻有效。即:时刻t_i时鼠标位置恰好在(x_i,y_i)才能得分。
Kaguya所做的工作就是在这些时刻间移动鼠标。
对于样例:选择点击第2、4个圆圈。
时间[0,2]内,鼠标从(0,0)移动到(0,2),速度为1,并在时刻2得分。
时间[2,4]内,鼠标从(0,2)移动到(2,0),速度为sqrt(2),并在时刻4得分。
因此答案为sqrt(2), a=1 b=2 c=1
Data Constraint
Solution
我们发现题目要求“最大值最小”,所以我们要想到二分。
然后通过DP算路径(路径用一个数组存),然后找最大值就行了。
DP时间复杂度:O(n2)
其实求a,b,c没有想象中的这么难。
我们将b的根号拆开,然后将b中质因数x的指数为2n的统统去掉,然后a=a∗xn
然后a与c再约分就行了。
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 2010
#define fo(i,a,b) for(i=a;i<=b;i++)
#define LF double
using namespace std;
LF dis[N][N],l,r,mid,ans,t[N],x[N],y[N];
int a,b,c,d,n,i,j,k,m,A1,A2,f[N],pred[N];
int gcd(int x,int y)
{
if (y==0) return x;else return gcd(y,x%y);
}
int main()
{
scanf("%d%d",&n,&k);
fo(i,1,n) scanf("%lf%lf%lf",&t[i],&x[i],&y[i]);
fo(i,0,n-1)
fo(j,i+1,n)
dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))/(t[j]-t[i]);
l=0;
r=100000000;
while (r-l>0.001)
{
bool p=0;
mid=(l+r)/2;
memset(f,0,sizeof(f));
ans=0;
fo(i,0,n)
{
fo(j,0,i-1)
if (dis[j][i]<=mid && f[j]+1>f[i])
{
f[i]=f[j]+1;
pred[i]=j;
}
if (f[i]==k)
{
for (m=i;m;m=pred[m])
{
if (dis[pred[m]][m]>ans)
{
A1=pred[m];
A2=m;
ans=dis[pred[m]][m];
}
}
p=1;
break;
}
}
if (p) r=mid;else l=mid;
}
a=1;
b=(x[A1]-x[A2])*(x[A1]-x[A2])+(y[A1]-y[A2])*(y[A1]-y[A2]);
c=t[A2]-t[A1];
fo(i,2,sqrt(b))
while (b%(i*i)==0)
{
a=a*i;
b=b/(i*i);
}
d=gcd(a,c);
a/=d;c/=d;
printf("%d %d %d",a,b,c);
}