这次烹饪比赛有 4 4 道菜品,小黎需要一道一道地制作,因为大赛规定要完成一道菜品后才能完成下一道菜品。每道菜品都有一个配方。其中第 i 道菜的配方共包含 � � s i 个步骤,完成每个步骤需要一些时间,可能不等,每个步骤的制作顺序可以随意调整。小黎只有两个灶台可以同时使用,菜品的每个步骤都只能在其中一个灶台上制作,一个灶台同一时间内只能进行一个步骤的制作。现在他想知道,在任意顺序制作的情况下,最短需要多长时间才能完成所有的菜品。c++
时间: 2024-03-23 14:38:12 浏览: 5
好的,下面是一个C++的实现,使用了动态规划的思想来解决这个问题:
```c++
#include <bits/stdc++.h>
using namespace std;
const int N = 15, M = 1 << N;
const int INF = 1e9;
int n;
int s[N], t[N][N], f[M];
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &s[i]);
for (int j = 0; j < s[i]; j++)
scanf("%d", &t[i][j]);
}
memset(f, 0x3f, sizeof f);
f[0] = 0;
for (int i = 0; i < (1 << n); i++)
{
int cnt = 0;
for (int j = 0; j < n; j++)
if (i >> j & 1)
cnt += s[j];
for (int j = 0; j < n; j++)
if (!(i >> j & 1))
{
int cost = 0, k = 0;
for (int u = 0; u < s[j]; u++)
{
int res = INF;
for (int v = 0; v < n; v++)
if ((i >> v & 1) && (k < cnt - s[v] || k >= cnt))
res = min(res, f[i ^ (1 << v)] + t[v][s[v] - 1] + cost);
cost += t[j][u];
k++;
f[i | (1 << j)] = min(f[i | (1 << j)], res + cost);
}
}
}
printf("%d\n", f[(1 << n) - 1]);
return 0;
}
```
这里的状态表示为 $f[i]$,表示完成状态为 $i$ 的所有菜品需要的最短时间。根据题目的要求,我们需要在每个状态下,枚举下一步制作的菜品,然后计算出制作该菜品的最短时间,从而得到下一个状态的最短时间。其中,状态转移方程为:
$$
f[i | (1 << j)] = \min\{f[i | (1 << j)], f[i \oplus (1 << v)] + t[v][s[v]-1] + cost\}
$$
其中,$i$ 表示当前的状态,$j$ 表示下一个要制作的菜品,$v$ 表示当前状态中已经完成的步骤所属的菜品,$cost$ 表示当前制作菜品 $j$ 的时间。
时间复杂度为 $O(3^n n^2)$。