【USACO2002 Feb】奶牛自行车队

【USACO2002 Feb】奶牛自行车队

Time Limit: 1000 ms Memory Limit: 131072 KBytes

Description

N 头奶牛组队参加自行车赛。车队在比赛时排成一列,需要绕场S 圈。由于空气阻力的作用,领队奶牛消耗的体力要比后面的多。每头奶牛的初始体力都是相同的,记作M,体力减为负数的奶牛只能中途退赛,体力也不会在比赛途中恢复,但最后只要有一位队员到达终点就算完成了比赛。

比赛最小的单位时间是分钟。车队在每分钟必须绕赛场整数圈,最少是每分钟一圈。如果车队在一分钟里绕场x圈,领队奶牛会消耗sqr(x)点体力,跟在后面的所有奶牛将会消耗X点体力。每分钟开始的时刻,车队可以自由选择是否换下领队奶牛,让其他奶牛做领队,并且设定这一分钟的速度。如果设定该分钟的速度为x圈,则要保证领队奶牛的体力至少要大于sqr(x)。

作为它们教练,请你计划一下,应采用什么样的策略才能让车队以最快的时间完成比赛?输入数据保证 S ≤ M,因此一定存在完成比赛的方案。

Input

第一行:三个整数 N,M 和 S,1 ≤ N ≤ 20, 1 ≤ S ≤ M ≤ 100

Output

单个整数:表示最早完成比赛的时间

Sample Input

3 30 20

Sample Output

7

Hint

enter image description hereenter image description here(时间5领队的奶牛为C)

Solution

再来写一道dp

 

首先设计状态

 

不不不,我们先来看数据范围,1≤N≤20,1≤S≤M≤100,这么小(露出邪♂恶的微笑)

 

那就大胆设计状态f[i][j][k]表示领头的为第i只奶牛走了j圈领头的奶牛体力剩余k的最少时间

 

为什么这么设计呢?

 

因为每头奶牛的初始体力相同,如果在最优解中该头奶牛还需继续领头则不要换奶牛

 

那么开始转移,这道题的转移比较绕,因为数据小方程维数多,这道题有4重循环,很难受,其实这题的转移只需分为两种状况,一种是由当前领头奶牛继续领头,另一种是由上一头奶牛换成这头奶牛

 

接下来挂方程:

$f\left[ i \right]\left[ j \right]\left[ k \right] = min\left\{ \begin{array}{l}f[i][j - l][k + l*l],1 < = l < = j\& \& k + l*l < = m - j + l\\f[i - 1][j - l][t],1 < = l < = j\& \& 0 < = t < = m\& \& m - j + l = = k + l{\rm{*}}l\end{array} \right.$

 

这里还有一个小优化(并不知道有没有用),当你处理出f[i][j][k]时,你便可以更新f[i+1][j][m-j](即换一只奶牛)

 

答案只需扫一遍f[i][s][k]取min即可

 

代码如下OwO

 
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 int f[25][105][105],n,m,s;
 7 int main()
 8 {
 9     memset(f,127,sizeof(f));
10     scanf("%d%d%d",&n,&m,&s);
11     f[1][0][m]=0;
12     for (int i=1;i<=n;i++)
13         for (int j=1;j<=s;j++)
14             for (int k=0;k<=m;k++)
15                 for (int l=1;l<=j;l++){
16                 int p=pow(l,2)+k;if (p<=m-j+l){
17                 f[i][j][k]=min(f[i][j][k],f[i][j-l][p]+1);
18                 f[i+1][j][m-j]=min(f[i+1][j][m-j],f[i][j][k]);
19                 }
20             }
21     int ans=2147483647;
22     for (int i=1;i<=n;i++)
23         for (int k=0;k<=m;k++) ans=min(ans,f[i][s][k]);
24     printf("%d",ans);
25     return 0;
26 }
View Code

 

 
 

 

转载于:https://www.cnblogs.com/Cool-Angel/p/7738208.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值