![](https://i-blog.csdnimg.cn/blog_migrate/27f086712c2769d3752b66652bc16323.png)
题意:给你n和p,有n个敌人要打败,每个敌人有p1, p2, t1, t2, w1, w2, 代表如果你的p大于p2的话,那么将只花费t2秒,在p1和p2之间的话,就需要在t2到t1的线性比时间,w1代表力量加一药水的数量,w2代表力量翻倍药水的数量,要按顺序消灭敌人,求最短的时间。
解题思路:dp,设dp[i][j][k]表示第i个敌人,此时j的力量的,w2药水的数量。有加一的药水肯定立马用掉,但是翻倍的不能确定是否使用,所以需要记录起来,w2的最大值是不超过7,力量最大不超过100。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
double dp[1010][110][10];
int f[10];
int n, p, p1, p2, t1, t2, w1, w2;
void init()
{
f[0] = 1;
for (int i = 1; i < 10; i++) f[i] = f[i - 1] * 2;
}
double cal(int p1, int p2, int t1, int t2, int p)
{
if (p >= p2) return t2;
if (p < p1) return 1.0 * INF;
return 1.0 * t1 - 1.0 * (t1 - t2) / (p2 - p1) * (p - p1);
}
int main()
{
init();
while (~scanf("%d %d", &n, &p))
{
if (!n && !p) break;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= 105; j++)
for (int k = 0; k <= 8; k++)
dp[i][j][k] = 1.0 * INF;
dp[0][p][0] = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d %d %d %d", &p1, &p2, &t1, &t2, &w1, &w2);
for (int j = 1; j <= 100; j++)
for (int k = 0; k <= 7; k++)
for (int l = 0; l <= k + w2; l++)
{
if (fabs(dp[i - 1][j][k] - 1.0 * INF) < eps) continue;
int tmp1 = min(100, j + w1);
int tmp2 = min(tmp1 * f[l], 100);
int tmp3 = min(k + w2 - l, 7);
dp[i][tmp2][tmp3] = min(dp[i][tmp2][tmp3], dp[i - 1][j][k] + cal(p1, p2, t1, t2, j));
}
}
double ans = 1.0 * INF;
for (int i = 1; i <= 100; i++)
for (int j = 0; j <= 7; j++)
ans = min(ans, dp[n][i][j]);
if (fabs(ans - 1.0 * INF) < eps) printf("Impossible\n");
else printf("%.2lf\n", ans);
}
return 0;
}