题目大意
给出一些按顺序出现的点(x,y)和出现时间,问经过k个点所需要的最小速度,初始在(0,0)速度要保留根号。
解题思路
答案可能值有n^2个(两两点对),二分答案后n^2dp判断即可。
code
using namespace std;
int const maxn=2000,inf=2147483647;
int n,K,t[maxn+10],x[maxn+10],y[maxn+10],f[maxn+10],dis[maxn+10][maxn+10],tim[maxn+10][maxn+10];
int gc(int x,int y){
int z;if(!y)return 1;
for(;z=x%y;){
x=y;
y=z;
}
return y;
}
struct rec{
int x,y,t,d;
friend bool operator<(rec x,rec y){
return 1ll*x.d*y.t<1ll*y.d*x.t;
}
};
rec an[(maxn+10)*(maxn+10)];
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&n,&K);
fo(i,1,n)scanf("%d%d%d",&t[i],&x[i],&y[i]);
int cnt=0;
fo(i,0,n)
fo(j,i+1,n)
if(i+n-j+1>=K){
an[++cnt].x=abs(x[i]-x[j]),
an[cnt].y=abs(y[i]-y[j]),
tim[i][j]=an[cnt].t=(t[i]-t[j])*(t[i]-t[j]),
dis[i][j]=an[cnt].d=an[cnt].x*an[cnt].x+an[cnt].y*an[cnt].y;
}
sort(an+1,an+cnt+1);
int l=1,r=cnt;
for(;l!=r;){
int m=(l+r)/2,ans=0;
fo(i,1,n)f[i]=-inf;f[0]=0;
fo(i,1,n){
fo(j,0,i-1)
if(1ll*dis[j][i]*an[m].t<=1ll*an[m].d*tim[j][i])f[i]=max(f[i],f[j]+1);
ans=max(ans,f[i]);
if(ans>=K)break;
}
if(ans>=K)r=m;
else l=m+1;
}
int a=1,b=an[l].d,c=sqrt(an[l].t);
fo(i,2,28284)
for(;b%(i*i)==0;a*=i,b/=i*i);
int gcd=gc(a,c);a/=gcd;c/=gcd;
printf("%d %d %d",a,b,c);
return 0;
}