题意:一个团队有n只奶牛进行骑自行车环跑,如果一分钟跑x圈,领跑的消耗x * x体力,而后面跟跑的消耗x体力。没有体力的牛可以退场,有一头牛通过重点即算完成比赛。给定N, E, D三个数,表示有N头奶牛,每头奶牛具有初始能量值E,D表示需要环跑的圈数。问奶牛能否完成环跑,如果不能,输出0,否则,输出环跑的最短时间。
思路:dp。显然每头牛轮流领跑,没体力了就退。dp[i][j][k] 表示第i头牛正在领跑(前i-1头已经退场),第i头牛已经消耗了j体力,队伍已经跑完了k圈所用的最小时间。
那么dp[i][j][k] 可以用来更新dp[i][j+a*a][k+a]即当前分钟跑a圈,没更新一次立即更新dp[i+1][k+a]k+a],表示当前分钟跑完第i头牛就退场。最后看看第三维=D(即跑完全程)的最小dp值。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define N 105
int dp[22][N][N];
int n,e,m;
int main(){
int i,j,k,a,res=INF;
scanf("%d %d %d",&n,&e,&m);
clr(dp, 0);
for(i = 1;i<=n;i++)
for(j = 0;j<=e;j++)
for(k = 0;k<=m;k++)
dp[i][j][k] = INF;
dp[1][0][0] = 0;
for(i = 1;i<=n;i++)
for(j = 0;j<=e;j++)
for(k = 0;k<=m;k++)
for(a = 1;j+a*a<=e&&k+a<=m;a++){
dp[i][j+a*a][k+a] = min(dp[i][j+a*a][k+a],dp[i][j][k]+1);
dp[i+1][k+a][k+a] = min(dp[i+1][k+a][k+a],dp[i][j+a*a][k+a]);
}
for(i = 1;i<=n;i++)
for(j = 1;j<=e;j++)
if(dp[i][j][m])
res = min(res,dp[i][j][m]);
printf("%d\n",res);
}