博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 1946 Cow Cycling(抽象背包, 多阶段DP)
阅读量:5018 次
发布时间:2019-06-12

本文共 3226 字,大约阅读时间需要 10 分钟。

Description

The cow bicycling team consists of N (1 <= N <= 20) cyclists. They wish to determine a race strategy which will get one of them across the finish line as fast as possible. 
Like everyone else, cows race bicycles in packs because that's the most efficient way to beat the wind. While travelling at x laps/minute (x is always an integer), the head of the pack expends x*x energy/minute while the rest of pack drafts behind him using only x energy/minute. Switching leaders requires no time though can only happen after an integer number of minutes. Of course, cows can drop out of the race at any time. 
The cows have entered a race D (1 <= D <= 100) laps long. Each cow has the same initial energy, E (1 <= E <= 100). 
What is the fastest possible finishing time? Only one cow has to cross the line. The finish time is an integer. Overshooting the line during some minute is no different than barely reaching it at the beginning of the next minute (though the cow must have the energy left to cycle the entire minute). N, D, and E are integers.

Input

A single line with three integers: N, E, and D 

Output

A single line with the integer that is the fastest possible finishing time for the fastest possible cow. Output 0 if the cows are not strong enough to finish the race. 

Sample Input

3 30 20

Sample Output

7

Hint

[as shown in this chart: 	                            leader E 	               pack  total used this 	time  leader  speed   dist   minute 	  1      1      5       5      25 	  2      1      2       7       4 	  3      2*     4      11      16 	  4      2      2      13       4 	  5      3*     3      16       9 	  6      3      2      18       4 	  7      3      2      20       4 	* = leader switch

思路:

1. dp[i][d][e] 表示第 i 头牛使用能量 e 跑 d 圈的最小分钟数假如该牛无法跑完, 则值为 INF. 

 

讨论:

当第 i 头牛领跑时

锁定一头牛后, 假设 dp[d][e] 对应牛使用能量 e 跑 d 圈的最小分钟数, dp[][] 可用完全背包计算 

for(int d = 1; d <= D; d++) {    for(int e = 1; e <= E; e++) {    	for(int k = 1; k*k <= e && k <= d; k ++) {//完全背包    		dp[d][e] = min(dp[d][e], dp[d-k][e-k*k]+1)    	}    }        }

 

第 i 头牛总是作为领跑, 第 i+1 头牛享受 i 头牛的成果

dp[i+1][d][d] = min(dp[i+1][d][d], dp[i][d][e]);

这个状态转移的方程理解为: 当前由第 i 头牛领跑, 第 i+1 头牛享受成果, 即跑了几圈就耗费多少能量. 注意, dp[i][d][e] 中, e >= d, 不管第 i 头牛怎么跑, 只要它跑了 d 圈, i+1 头牛就耗费了 d 的能量. 

dp[i+1][d][d] 是对第 i+1 头牛进行初始化, 在代码中也可以看出, 第 i 头牛更新第 i+1 头牛的dp[][][]

 

总结:

1. 每头牛, 自己跑的时候使用了一次 dp, 牛与牛之间又使用了一次 dp

2. 递推关系仅建立在相邻的两头牛之间, 后面一头牛继承前面那头牛的最小时间

 

代码:

#include 
using namespace std;const int INF = 0X3F3F3F3F;const int MAXN = 30;int N, E, D;int dp[30][110][110];int main() { freopen("E:\\Copy\\ACM\\poj\\1661\\in.txt", "r", stdin); while(cin >> N >> E >> D) { for(int i = 0; i <= N; i ++) for(int j = 0; j <= D; j ++) for(int k = 0; k <= E; k++) dp[i][j][k] = INF; dp[1][0][0] = 0; for(int i = 1; i <= N; i ++) { for(int j = 1; j <= D; j++) { for(int k = 1; k <= E; k++) { for(int s = 1; s*s <= k && s <= j; s ++) { dp[i][j][k] = min(dp[i][j][k], dp[i][j-s][k-s*s]+1); } dp[i+1][j][j] = min(dp[i+1][j][j], dp[i][j][k]); // 第 i+1 头牛继承第 i 头牛的成果 } } } int ans = INF; for(int k = 1; k <= E; k ++) ans = min(ans, dp[N][D][k]); cout << ans << endl; } return 0;}

  

转载于:https://www.cnblogs.com/xinsheng/p/3450479.html

你可能感兴趣的文章
C#开发点滴记录
查看>>
[COJ0970]WZJ的数据结构(负三十)
查看>>
Fragment使用
查看>>
WCF和ASP.NET Web API在应用上的选择(转)
查看>>
数据库操作指令
查看>>
风之语.人在职场也需要'备胎'
查看>>
学习C语言第一天:在windows下使用gcc的条件
查看>>
浅谈Python web框架
查看>>
放假啦
查看>>
实验报告2
查看>>
如何使用fmt标签
查看>>
灵活使用Win+R快捷键提高工作效率
查看>>
2017-2018-1 20155201 《信息安全系统设计基础》第十一周学习总结
查看>>
用ScrollView解决Android屏幕显示不全的问题
查看>>
Java中的Filter过滤器
查看>>
css固定姓名显示长度,排列更整齐
查看>>
游标简单的使用
查看>>
行业不限凡事细心观察才会发现万物都是在变化之中
查看>>
net core发邮件——MimeKit
查看>>
[0014] HDFS 常用JAVA 操作实战
查看>>