SPOJ RENT(简单动归)
暑期个人赛第四场
快被这道题搞死了。又是题意理解有误
题意:有n个订单,每个订单有开始时间,占用时间,愿意支付的money3个参数,要求在这n个订单中选择不冲突的的订单使得money总和最大。
思路:对订单的开始时间或者结束时间排序,然后用动归求最优解,
如果对开始时间从小到大排序,则动归顺序应从后向前,如果对结束时间从小到大排序,则动归顺序应该从前向后。
对于每个订单决策就是选择or丢去
状态:dp[i]表示到第i个订单时,money所能取得的最大值
状态转移:dp[i] = max(dp[i-1], dp[x]+piece[i]);
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define M 10005 typedef struct { int st, et, pe; }oo; int n, dp[M]; oo a[M]; int comp(const oo x, const oo y) {return x.et < y.et; } int find(int l, int r, int x) { if(x<a[1].et) return 0; int mid; while(l<=r) { mid = (r+l)/2; if(x>=a[mid].et) l = mid+1; else r = mid-1; } return x<a[l].et?l-1:l; } int main () { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; ++i) {scanf("%d %d %d",&a[i].st, &a[i].et, &a[i].pe); a[i].et+=a[i].st; } sort(a+1,a+1+n,comp); dp[0] = 0; for(int i = 1; i <= n; ++i) { dp[i] = dp[i-1]; int j = find(1,i-1,a[i].st); dp[i] = max(dp[i],dp[j]+a[i].pe); } printf("%d\n",dp[n]); } return 0; }