#include using namespace std; int se; // 学期总数 int sx; // 学分上限 int cl; // 课程数量 int ren[12], fe[12], re[12][105]; struct Class { string id; // 课程编号 int sx; // 学分 int xq; int sel; // 是否已经选择 int pren, nexn; // 先修课程数量 int ppren; // use for topo string pre[105]; // 先修课程 string next[105]; // 后续课程 } ss[105]; void pt(int detail = 0) { // print for (int i = 0; i < cl; i++) { cout << ss[i].id << " " << ss[i].sx << " " << ss[i].pren << " " << ss[i].nexn << endl; if (!detail) continue; if (ss[i].pren > 0) { cout << "pre:" << endl; for (int j = 0; j < ss[i].pren; j++) { cout << ss[i].pre[j] << " "; } cout << endl; } if (ss[i].nexn > 0) { cout << "next:" << endl; for (int j = 0; j < ss[i].nexn; j++) { cout << ss[i].next[j] << " "; } cout << endl; } cout << endl; } } // 寻找 id int fd(string id) { for (int i = 0; i < cl; i++) { if (ss[i].id == id) { return i; } } return -1; } // 去除字符串两边空格和换行符 string ql(string s) { int l = 0, r = s.length() - 1; while (s[l] == ' ' || s[l] == '\n') l++; while (s[r] == ' ' || s[r] == '\n') r--; return s.substr(l, r - l + 1); } // 寻找先修课程的最迟学期 int xz(int i) { // cout << ss[i].id << " " << ss[i].pren << endl; if (ss[i].pren == 0) return 0; int maxn = 0; for (int j = 0; j < ss[i].pren; j++) { int fid = fd(ss[i].pre[j]); if (ss[fid].xq > maxn) { maxn = ss[fid].xq; } } return maxn + 1; } // 寻找后修课程的最早学期 int xz2(int i) { if (ss[i].nexn == 0) return se; int minn = se; for (int j = 0; j < ss[i].nexn; j++) { int fid = fd(ss[i].next[j]); if (ss[fid].xq < minn) { minn = ss[fid].xq; } } return minn; } // 拓扑排序,将排好序的id 放入sorted void topo() { int sorted[105] = { 0 }; int cnt = 0; queue q; for (int i = 0; i < cl; i++) { if (ss[i].ppren == 0) { q.push(&ss[i]); } } while (!q.empty()) { Class* tmp = q.front(); sorted[cnt] = fd(tmp->id); q.pop(); cnt++; for (int i = 0; i < tmp->nexn; i++) { ss[fd(tmp->next[i])].ppren--; if (ss[fd(tmp->next[i])].ppren == 0) { q.push(&ss[fd(tmp->next[i])]); } } } if (cnt != cl) { cout << "error" << endl; exit(0); } Class newss[105]; // 将 ss 顺序改为 sorted 顺序 for (int i = 0; i < cl; i++) { newss[i] = ss[sorted[i]]; } for (int i = 0; i < cl; i++) { ss[i] = newss[i]; } } void avgf() { // 计算平均每学期学习数量 int avg = cl / se; // cout << avg << endl; // 按从后向前,如果学期学习数量小于平均值,则将前面的课程往后移动 for (int i = se - 1; i >= 1; i--) { if (ren[i] < avg) { for (int j = i - 1; j >= 0; j--) { // cout << j << " " << ren[j] << endl; if (ren[j] <= 0) continue; int flag = 0; for (int ii = 0; ii < ren[j] && ren[i] < avg; ii++) { int c = re[j][ii]; // cout << " " << ss[c].id << " " << xz2(2)<< endl; // cout << c << endl; if (xz2(c) > i) { // 把 c 课程放到 i 学期 re[i][ren[i]++] = c; ss[c].xq = i; // 把 c 课程从 j 学期删除 for (int jj = ii; jj < ren[j] - 1; jj++) { re[j][jj] = re[j][jj + 1]; } ren[j]--; flag = 1; } // 如果 i 学期中的课程数量大于平均值,则跳出循环 if (ren[i] >= avg) { break; } if (flag == 1) { ii = -1; flag = 0; } } } } } } void pte() { for (int i = 0; i < se; i++) { if (ren[i] == 0) continue; cout << "学期 " << i + 1 << " 学分 " << fe[i] << " 课程数 " << ren[i] << " 课程:"; for (int j = 0; j < ren[i]; j++) { cout << ss[re[i][j]].id << " "; } cout << endl; } } int main() { freopen("in.txt", "r", stdin); cin >> se >> sx; if (se <= 0 || sx <= 0 || se > 6 || sx > 10) { cout << "error" << endl; exit(0); } cin >> cl; if (cl <= 0 || cl > 12) { cout << "error" << endl; exit(0); } for (int i = 0; i < cl; i++) { cin >> ss[i].id; ss[i].id = ql(ss[i].id); } for (int i = 0; i < cl; i++) { cin >> ss[i].sx >> ss[i].pren; ss[i].ppren = ss[i].pren; for (int j = 0; j < ss[i].pren; j++) { string tmp; cin >> tmp; tmp = ql(tmp); if (tmp.size() == 0) continue; int fid = fd(tmp); if (fid == -1) { cout << "error" << endl; exit(0); } ss[i].pre[j] = ss[fid].id; ss[fid].next[ss[fid].nexn++] = ss[i].id; } } // pt(1); topo(); // pt(1); for (int i = 0; i < cl; i++) { ss[i].xq = xz(i); } int ttc = 0; for (int i = 0; i < se; i++) { for (int j = 0; j < cl; j++) { // 判断是否已选择 if (ss[j].sel == 1) { continue; } // 判断是否学分超过上限 if (ss[j].sx + fe[i] > sx) { continue; } // 判断是否先修课程已经学习 int flag = 0; for (int k = 0; k < ss[j].pren; k++) { int fid = fd(ss[j].pre[k]); if (ss[fid].sel == 0) { flag = 1; break; } } if (flag == 1) { continue; } // 选择该课程 ss[j].sel = 1; fe[i] += ss[j].sx; re[i][ren[i]++] = j; ttc++; } } // 判断是否全部选中 if (ttc != cl) { cout << "error" << endl; exit(0); } // for (int i = 0; i < cl; i++) { // cout << ss[i].id << " " << ss[i].xq << endl; // } // pte(); int kind; cin >> kind; if (kind != 1 && kind != 2) { cout << "error" << endl; exit(0); } // 输入分配方式,1是负担均匀,2是尽早学习 if (kind == 1) { avgf(); } else if (kind == 2) { // 本来就是今早分配的,无需更改 } else { cout << "error" << endl; exit(0); } // 输出最终结果 pte(); return 0; }