【发布时间】:2017-10-04 23:21:36
【问题描述】:
这是来自 informatica olympiad 的一个问题,我一直试图解决这个问题。这对我来说很重要,因为这包含一个我在很多问题中看到的潜在基本问题。
给 N 个公民参加一个活动,他们必须在一台计算机上编程,吃巧克力,然后吃甜甜圈。 time ,第 i 个公民为每个任务所花费的时间作为输入。每个公民必须按顺序完成任务,即先编程,然后吃巧克力,然后吃甜甜圈。任何数量的人一次都可以吃巧克力或甜甜圈,但由于计算机是一台,每次只有一个人可以编程。一次,他完成了,他会转向巧克力,下一个人将编程。任务是找出公民被派往编程的顺序,以使事件在最短的时间内结束,这个时间是输出。
我使用以下方法解决了这个问题: 如果我从第 i 个公民开始,那么对于剩下的 n-1 个公民,如果我找到时间 (tn-1) 则 tn = max((ni[0]+ni[1]+ni[2]), ni[0] + TN-1)。例如。: 18 7 6 23 10 27 20 9 14
然后 18+7+6, 18+23+10+27, 18+23+20+9+14, max 将是 84,但如果你从 23 开始,那么时间将是 74,这是更少的。
我实现了这种方法,我在这里展示它的代码。然而,对于我的方法来说,复杂度是 O(n!)。我可以看到潜在的重复子问题,所以我可以使用 DP 方法。但问题是我需要存储每个列表 i 到 j 的时间值,以便它可以以从 i 到 j 的任何 k 开头,依此类推。这个存储过程又会很复杂并且需要 n!贮存。如何解决这个问题和类似的问题?
这是我的方案:
#include <iostream>
#include <vector>
#include <climits>
int min_time_sequence(std::vector<std::vector<int> > Info, int N)
{
if (N == 0) return 0;
if (N == 1)
{
int val = Info[0][0] + Info[0][1] + Info[0][2];
return val;
}
std::vector<std::vector<int> > tmp = Info;
int mn = INT_MAX;
for (int i = 0; i < N; ++i)
{
//prepare new list
tmp.erase(tmp.begin()+i);
int mn = min_time_sequence(tmp, N-1);
int v1 = Info[i][0] + mn;
int v2 = Info[i][0] + Info[i][1] + Info[i][2];
int larger = v1 > v2 ? v1 : v2;
if (mn > larger) mn = larger;
}
return mn;
}
int main()
{
int N;
std::cin>>N;
std::vector<std::vector<int> > Info;
//input
for (int i = 0; i < N; ++i)
{
std::cin>>Info[i][0];
std::cin>>Info[i][1];
std::cin>>Info[i][2];
}
int mx = 0;
if (N > 0)
mx = min_time_sequence(Info, N);
std::cout<<mx<<std::endl;
return 0;
}
【问题讨论】:
-
这是一个加权间隔调度问题,增加了一些额外的复杂性以确定作业是否兼容。你可以在 O(nlogn) 时间内完成一些工作,一旦你知道要搜索什么,网络上就有很多资源。
-
这不是加权区间调度问题,我也想不出怎么近似。在这里,没有开始时间和结束时间,任何公民都可以开始任何时间,那么如何调和呢?如果你想通了,你能提供一种方法吗?
-
这里是一个类似问题的链接,但我看不出所提出的方法是如何工作的? stackoverflow.com/questions/28648370/…
标签: c++ algorithm dynamic-programming