题意:有n个学习领域,每个领域有m个课程,学习第i个领域的第j个课程可以获得sij个技能点,在每个领域中选择一个课程,要求获得的n个技能点的最大值减最小值最小,输出符合要求的策略。
解法:尺取法。将课程的技能点按值进行排序,同时要记录每个值对应的领域,用尺取法选择第一段包含全部领域的区间,区间的边界即为最值,然后将左指针逐步右移,直到出现有的领域没有选课,继续右移右指针,直到结束。当右指针已移到最右的时候需要特判,只移动左指针。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; int c[205]; struct node { int a, b, c; bool operator < (const node &tmp) const { if(a == tmp.a) return b < tmp.b; return a < tmp.a; } bool operator == (const node &tmp) const { return a == tmp.a && b == tmp.b; } node(int a, int b, int c) : a(a), b(b), c(c){} node() {} }; vector <node> v; int n; bool judge(int cnt[]) { for(int i = 0; i < n; i++) if(!cnt[i]) return false; return true; } int main() { while(~scanf("%d", &n)) { v.clear(); for(int i = 0; i < n; i++) { scanf("%d", &c[i]); } if(n == 1 && c[0] == 1) //需要特判否则RE { int x; scanf("%d", &x); printf("0\n1\n"); continue; } for(int i = 0; i < n; i++) { for(int j = 0; j < c[i]; j++) { int s; scanf("%d", &s); v.push_back(node(s, i, j + 1)); } } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); int len = v.size(); int flag = 0; int now = -1; int cnt[205] = {0}; int l = 0, r = 0; cnt[v[0].b] = 1; int ans = INT_MAX, pl, pr; for(; l < len;) { if(!flag) { r++; cnt[v[r].b]++; if(judge(cnt)) { flag = 1; if(v[r].a - v[l].a < ans) { ans = v[r].a - v[l].a; pl = l, pr = r; } continue; } } else { if(~now && r < len - 1) { r++; cnt[v[r].b]++; if(cnt[now]) { now = -1; if(v[r].a - v[l].a < ans) { ans = v[r].a - v[l].a; pl = l, pr = r; } } } else { if(r == len - 1) { cnt[v[l].b]--; l++; if(judge(cnt)) { if(v[r].a - v[l].a < ans) { ans = v[r].a - v[l].a; pl = l, pr = r; } } continue; } cnt[v[l].b]--; if(!cnt[v[l].b]) { now = v[l].b; l++; } else { l++; if(v[r].a - v[l].a < ans) { ans = v[r].a - v[l].a; pl = l, pr = r; } } } } } printf("%d\n", ans); int prt[205]; for(int i = pl; i <= pr; i++) { prt[v[i].b] = v[i].c; } for(int i = 0; i < n; i++) { if(i) printf(" "); printf("%d", prt[i]); } puts(""); } return 0; }
时间: 2024-11-06 07:35:44