这个题真的是太神了。。。
从一開始枚举到最后n方的转化,各种优化基本都用到了极致。。。。
FQW的题解写了好多,个人感觉我全然没有在这里废话的必要了
直接看这里
各种方法真的是应有尽有
大概说下
首先能够想到一个KM算法求二分图最大代权匹配的问题对吧
左边是任务右边是时间
可是这个是三次方啊
那我们就按价值排序,这样就不用代权匹配了可是还是三方
可是左边在右边的连线是单调的。。。
所以就能够贪心推断了。。。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define MAX 5010 #define rep(i,j,k) for(int i = j; i <= k; i++) using namespace std; int n, Link[MAX]; long long ans = 0; int b[MAX]; struct wbysr { int Begin, end, value; } a[MAX]; bool cmp (wbysr a1, wbysr a2) { return a1.Begin < a2.Begin || (a1.Begin == a2.Begin && a1.end < a2.end); } bool cmp2 (wbysr a1, wbysr a2) { return a1.value > a2.value; } bool find (int now, int x) { if (b[x] > a[now].end) return 0; if (!Link[x]) { Link[x] = now; return 1; } int j = Link[x]; if (a[now].end > a[j].end) return find (now,x + 1); else { if (find(j, x + 1)) { Link[x] = now; return 1; } } return 0; } int main() { scanf ("%d", &n); rep (i, 1, n) scanf ("%d%d%d", &a[i].Begin, &a[i].end, &a[i].value); sort (a + 1, a + 1 + n, cmp); int now = 0; rep (i, 1, n) { now = max (now + 1, a[i].Begin); b[i] = now; } sort (a + 1, a + 1 + n, cmp2); b[n+1] = 0x7fffffff / 3; rep (i, 1, n) { int j; for (j = 1; j <= n; j++) if (b[j] >= a[i].Begin && b[j] <= a[i].end) break; if (find(i, j)) ans += a[i].value; } cout << ans << endl; return 0; }
Bzoj2034 2009国家集训队试题 最大收益 贪心+各种优化+二分图
时间: 2024-11-09 00:01:26