pku 1946 Cow Cycling(DP)

对于一直骑行在非队首的选手,能量消耗和距离是相等的,这给了我们用DP来处理的条件。

DP[i][j]表示i个人骑行距离j的最短时间。

于是有DP[i+1][d]=DP[i][k]+min_time(E-k,d-k)(0<k<=d),min_time(i,j)表示队首的人有能量j,骑行距离i的最短时间。通过观察可以发现,对于给定的距离d个时间t,总是把d划分为尽量相等的t段时消耗的能量较少,这也即是min_time函数的求解方法。

 

#include <iostream> #define PI 3.14159265358979323846264338327950288 #define _clr(a,b) memset(a,b,sizeof(a)) template<class T> T _abs(T a) { if(a<0) return -a;return a;} template<class T> void get_min(T& a,T b) { if(a>b) a=b;} template<class T> void get_max(T& a,T b) { if(a<b) a=b;} using namespace std; int N,E,D; int DP[25][105]; const int INF=1000; int min_time(int d,int e) { if(d==0) return 0; int cost; for(int i=1;;i++) { int m=d/i; int k=d-m*i; cost=k*(m+1)*(m+1)+(i-k)*m*m; if(cost<=e) return i; } } int main() { scanf("%d%d%d",&N,&E,&D); if(E<D) { printf("0/n"); return 0; } for(int i=0;i<=N;i++) { for(int j=0;j<=D;j++) { DP[i][j]=INF; } } DP[0][0]=0; for(int i=1;i<=N;i++) { for(int j=0;j<=D;j++) { for(int d=0;d<=j;d++) { get_min(DP[i][j],DP[i-1][d]+min_time(j-d,E-d)); } } } printf("%d/n",DP[N][D]); return 0; }

你可能感兴趣的:(pku 1946 Cow Cycling(DP))