Music Festival Gym
阿新 • • 發佈:2018-12-18
傳送門:QAQ
題意:給你n組區間,每個居間都帶有權值,讓你選取一些區間使得區間不想交併且權值最大(要每組都至少有一個區間被選到)。
思路:n最多十組,我們就可以用二進位制來記錄當前唱歌的狀態,然後離散化區間點(這樣我們就可以用連續的點去表示這些區間),這樣就有dp【i】【j】,i表示當前的區間點,j表示當前的狀態,dp【i1】【j1】=dp【i】【j】+num【k】。每次尋找當前點往右 能更新的最近的一個區間(一切切的一切都是膜拜大佬的部落格來的,離散化真是個好東西)
附上程式碼:
#include<stdio.h> #include<cstring> #include<cstdlib> #include<algorithm> #include<map> #include<iostream> using namespace std; struct inst { int x, y; int sud; int id; }; inst ax[1100]; int dp[2100][1100]; int bn[2100]; int maxn[1100]; int tot, cnt; map<int, int>q; int cmp(inst a, inst b) { if (a.x!=b.x)return a.x < b.x; else return a.y < b.y; } int binary_s(int x) { int l = 0; int r = tot-1; int ans = tot-1; while (l <= r) { int mid = (l + r) / 2; if (ax[mid].x >= x) { ans = mid; r = mid - 1; } else l = mid + 1; } if (x > ax[ans].x) ans++; return ans; } int main(void) { int n; scanf("%d", &n); tot = 0; cnt = 0; q.clear(); memset(maxn, 0x8f, sizeof(maxn)); memset(dp, 0x8f, sizeof(dp)); for (int i = 1; i <= n; i++) { int m; scanf("%d", &m); for (int z = 0; z < m; z++) { scanf("%d %d %d", &ax[tot].x, &ax[tot].y,&ax[tot].sud); ax[tot].id = i-1; bn[cnt++] = ax[tot].x; bn[cnt++] = ax[tot].y; tot++; } } sort(bn, bn + cnt); cnt = unique(bn,bn + cnt) - bn; sort(ax, ax + tot, cmp); for (int i = 0; i < cnt; i++) { q[bn[i]] = i; } for (int i = 0; i < tot; i++) { ax[i].x = q[ax[i].x]; ax[i].y = q[ax[i].y]; } dp[0][0] = maxn[0] = 0; for (int i = 0; i < cnt; i++) { for (int j = 0; j < (1 << n); j++) { dp[i][j] = maxn[j] = max(dp[i][j], maxn[j]); if (dp[i][j] < 0) continue; int pos=binary_s(i); int pre = -1; for (int z = pos; z < tot; z++) { if (pre == -1 || pre == ax[z].x) pre = ax[z].x; else break; int x1 = ax[z].y; int jj = j | (1 << ax[z].id); int sum = dp[i][j] + ax[z].sud; dp[x1][jj] = max(dp[x1][jj], sum); } } } if (maxn[(1 << n) - 1] >= 0) printf("%d\n", maxn[(1 << n) - 1]); else printf("-1\n"); return 0; }