[USACO02FEB]Cow Cycling

洛谷题面

题目大意

奶牛自行车队由 \(n\) 名队员组成,他们正准备参加一个比赛,这场比赛的路程共有 \(d\) 圈。 车队在比赛时会排成一条直线,由于存在空气阻力,当骑车速度达到每分钟 \(x\) 圈时,领头的 奶牛每分钟消耗的体力为 \(x^2\),其它奶牛每分钟消耗的体力为 \(x\)

每头奶牛的初始体力值都是相同的,记作 \(e\)。如果有些奶牛在比赛过程中的体力不支,就会掉队,掉队的奶牛不能继续参加比赛。每支队伍最后只要有一头奶牛能到终点就可以了。

比赛规定,最小的计时单位是分钟,在每分钟开始的时候,车队要哪头奶牛负责领头,领头奶牛不能在这分数中内掉队,每分钟骑过的圈数也必须是整数。

请帮忙计划一下,采用什么样的策略才能让车队以最快的时间到达终点?

\(n\le 20,e,d\le 100\)

题目分析

\(dp_{i,j,k}\) 表示有 \(i\) 头牛掉队了,领头的牛体力为 \(j\),已经跑了 \(k\) 圈的最快时间。

根据定义,初始化 \(dp_{0,e,0}=0\)

采用刷表法来做。当前状态会延伸出两个状态:领头牛掉队了、领头牛接着跑。

领头牛接着跑时,掉队的牛数量不变,体力减少,圈数变多。

领头牛掉队时,掉队的牛数量加 \(1\),体力是最初的体力减去已跑圈数花费的体力,圈数也变多。

即去更新 \(dp_{i,j-speed^2,k+speed}\)\(dp_{i+1,e-k-speed,k+speed}\)

代码

//2022/3/7
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <climits>//need "INT_MAX","INT_MIN"
#include <cstring>//need "memset"
#include <numeric>
#include <algorithm>
#define enter() putchar(10)
#define debug(c,que) cerr << #c << " = " << c << que
#define cek(c) puts(c)
#define blow(arr,st,ed,w) for(register int i = (st);i <= (ed); ++ i) cout << arr[i] << w;
#define speed_up() cin.tie(0),cout.tie(0)
#define mst(a,k) memset(a,k,sizeof(a))
#define Abs(x) ((x) > 0 ? (x) : (-x))
const int mod = 1e9 + 7;
inline int MOD(int x) {
	while (x < 0) x += mod;
	while (x >= mod) x -= mod;
	return x;
}
namespace Newstd {
	char buf[1 << 21],*p1 = buf,*p2 = buf;
	inline int getc() {
		return p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1 << 21,stdin),p1 == p2) ? EOF : *p1 ++;
	}
	inline int read() {
		int ret = 0,f = 0;char ch = getc();
		while (!isdigit(ch)) {
			if(ch == '-') f = 1;
			ch = getc();
		}
		while (isdigit(ch)) {
			ret = (ret << 3) + (ret << 1) + ch - 48;
			ch = getc();
		}
		return f ? -ret : ret;
	}
	inline void write(int x) {
		if(x < 0) {
			putchar('-');
			x = -x;
		}
		if(x > 9) write(x / 10);
		putchar(x % 10 + '0');
	}
}
using namespace Newstd;
using namespace std;

const int INF = 0x3f3f3f3f;
const int ma1 = 25,ma2 = 105;
int dp[ma1][ma2][ma2];//dp[i][j][k]:有 i 头牛掉队了,领头的牛体力为 j,已经跑了 k 圈的最快时间 
int n,e,d;
int main(void) {
#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
#endif
	n = read(),e = read(),d = read();
	mst(dp,0x3f);
	dp[0][e][0] = 0;
	for (register int i = 0;i <= n; ++ i) {
		for (register int j = e;j >= 0; -- j) {
			for (register int k = 0;k <= d; ++ k) {
				int now = 1;//每分钟 now 圈
				while (now * now <= j && k + now <= d) {
					dp[i][j - now * now][k + now] = min(dp[i][j - now * now][k + now],dp[i][j][k] + 1);
					dp[i + 1][e - k - now][k + now] = min(dp[i + 1][e - (k + now)][k + now],dp[i][j][k] + 1);
					now ++;
				}
			}
		}
	}
	int ans = INF;
	for (register int i = 0;i < n; ++ i) {
		for (register int j = 0;j <= e; ++ j) {
			ans = min(ans,dp[i][j][d]);
		}
	}
	printf("%d\n",ans == INF ? 0 : ans);

	return 0;
}
posted @ 2022-03-07 22:47  Coros_Trusds  阅读(33)  评论(0编辑  收藏  举报