题意:中文题不解释了。。。
思路:一开始想在时间上dp,后来发现完成飞行的时间不一定是整数,于是转而对距离进行dp。由于只能在整数秒下达命令,所以除了最后一条指令外,其余指令必然运行了整数秒。那么,我们就可以枚举其余指令运行的时间了(能飞多高只和指令运行时间有关和顺序无关)。然后去掉最后一条指令后就是一个容量为L的01背包,最后答案再加上最后一条指令。所以枚举最后一个指令,n次背包即可。
代码:
//#pragma comment(linker, "/STACK:134217728,134217728") /*128Mb*/ //#pragma comment(linker,"/STACK:33554432") /*32Mb*/ //#pragma comment(linker,"/STACK:16777216") /*16Mb*/ #include <algorithm> #include <iostream> #include <string> #include <string.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; /*--in common define-----*/ #define N 100010 #define E 100010 #define ll long long const int INF =0x3fffffff; const int PRIME =999983; const int MOD =1000000007; const int MULTI =1000000007; const double EPS=1e-8; /*--end in common define-*/ /*--in common use--------*/ #define CUBE(x) ((x)*(x)*(x)) #define SQ(x) ((x)*(x)) #define ALL(x) x.begin(),x.end() #define CLR(x,a) memset(x,a,sizeof(x)) #define maxAry(a,n) max_element(a,a+(n)) #define minAry(a,n) min_element(a,a+(n)) inline bool isodd(int x){return x&1;} inline bool isodd(ll x) {return x&1;} /*--end in common use----*/ double dp[110]; int vx[110],vy[110]; int n,L; double gao(int x) { fill(dp,dp+L+1,-1); dp[0]=0; for(int i=0;i<n;i++){ if(i==x) continue; for(int j=L;j>=0;j--){ for(int k=0;k<=100;k++){ if(j-vx[i]*k<0 || dp[j-vx[i]*k]==-1) continue; if(dp[j]==-1) dp[j]=dp[j-vx[i]*k]+vy[i]*k-0.5*9.8*SQ(k); else dp[j]=max(dp[j],dp[j-vx[i]*k]+vy[i]*k-0.5*9.8*SQ(k)); } } } double ans=-INF; for(int i=0;i<=L;i++){ if(dp[i]==-1) continue; double t=1.0*(L-i)/vx[x]; ans=max(ans,dp[i]+vy[x]*t-0.5*9.8*SQ(t)); } return ans; } int main() { int re,Case=1; double ans; scanf("%d",&re); while(re--){ scanf("%d%d",&n,&L); for(int i=0;i<n;i++) scanf("%d%d",&vx[i],&vy[i]); ans=-INF; for(int i=0;i<n;i++) ans=max(ans,gao(i)); printf("Case %d: %.3lf\n",Case++,ans); } return 0; }