更新第六题

This commit is contained in:
Luthics 2023-11-29 15:10:18 +08:00
parent dda94299d0
commit fc7b8c3f8d
2 changed files with 296 additions and 0 deletions

16
6/in.txt Normal file
View File

@ -0,0 +1,16 @@
6 10
12
C01 C02 C03 C04 C05 C06 C07 C08 C09 C10 C11 C12
2 0
3 1 C01
4 2 C01 C02
3 1 C01
2 2 C03 C04
3 1 C11
4 2 C03 C05
4 2 C03 C06
7 0
5 1 C09
2 1 C09
3 3 C01 C09 C10
1

280
6/main.c
View File

@ -0,0 +1,280 @@
#include <bits/stdc++.h>
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<Class*> 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;
}