徐州联赛选拔赛 高效安排人员

题目链接

思路:这是一道动态规划的题目,估计好多人去用贪心算法了,反正比赛时我想的贪心策略很容易找到反例Orz。题目就相当于选取一些区间去覆盖[0,T],每个区间有个价格,要求总价格最小。容易想到,如果覆盖[0,T]区间的价格是最小的,那么覆盖[0,T']的价格也必须是最小的,说明这个问题具有最优子结构性质。但是T的范围实在太大了,直接动态规划肯定是不行的。考虑到存在很多等效的时间点,我们可以把每个区间的时间离散化,但还保证他们的相对位置,这就把数据压缩到很小了,最多20W。然后对离散化后的时间进行动态规划,定义dp[i]表示覆盖[0,i]所需的最小费用,更新dp数组采用刷表法,如果i是某个区间的左端点,则对那个区间内的dp值进行更新:dp[j]=min(dp[j],dp[i]+v)。对于某些极端数据,这种做法是不能通过的,需要用线段树维护dp数组,就比较麻烦了,但好在OJ上并没有极端数据。

AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6  
 7 const int inf = 1000000000;
 8 struct Car
 9 {
10     int l, r;
11     int v;
12 };
13 Car car[100010];
14 int x[200010];
15 int dp[200010];
16 vector<int> vec[200010];
17  
18 int main()
19 {
20     int t;
21     scanf("%d", &t);
22     while (t--)
23     {
24         int n, t;
25         scanf("%d%d", &n, &t);
26         int cnt = 0;
27         for (int i = 0; i < n; i++)
28         {
29             scanf("%d%d%d", &car[i].l, &car[i].r, &car[i].v);
30             x[cnt++] = car[i].l;
31             x[cnt++] = car[i].r;
32         }
33         // 离散化时间
34         sort(x, x + cnt);
35         cnt = unique(x, x + cnt) - x;
36         for (int i = 0; i < n; i++)
37         {
38             car[i].l = lower_bound(x, x + cnt, car[i].l) - x;
39             car[i].r = lower_bound(x, x + cnt, car[i].r) - x;
40             // 由于起点为l的区间可能不止一个 所以这里采用vector存下所有起点为l的编号
41             vec[car[i].l].push_back(i);
42         }
43         // 初始化dp数组
44         fill(dp, dp + cnt, inf);
45         // 如果起点没有可能被覆盖直接输出无解
46         if (vec[0].size() == 0)
47         {
48             puts("-1");
49             continue;
50         }
51         for (int i = 0; i < vec[0].size(); i++)
52             for (int j = car[vec[0][i]].l; j <= car[vec[0][i]].r; j++)
53                 dp[j] = min(dp[j], car[vec[0][i]].v);
54         for (int i = 1; i < cnt; i++)
55         {
56             for (int j = 0; j < vec[i].size(); j++)
57                 for (int k = car[vec[i][j]].l + 1; k <= car[vec[i][j]].r; k++)
58                     dp[k] = min(dp[k], dp[i] + car[vec[i][j]].v);
59             vec[i].clear();
60         }
61         printf("%d\n", dp[cnt - 1] == inf ? -1 : dp[cnt - 1]);
62     }
63     return 0;
64 }
原文地址:https://www.cnblogs.com/iRedBean/p/5379905.html