标签:
思路:这是一道动态规划的题目,估计好多人去用贪心算法了,反正比赛时我想的贪心策略很容易找到反例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 }
标签:
原文地址:http://www.cnblogs.com/iRedBean/p/5379905.html