题目描述
新学期到了,白兔又要开始选课了。
一周有5天,每天6个时间段可以排课。学校一共开设了n门课程,第i门课程一共有m[i]个老师开设,每个老师会选择k[i]个时间段上课。白兔如果选了这门课,可以在这m[i]个老师中任意挑选一个老师,但是必须参加这个老师的所有时间段
现在,你需要帮助白兔求出,他选的课占用的时间段总和最大是多少(即所选课程的k[i]之和)?
输入格式
第一行一个整数n表示学校开设的课程数量
接下来n行,每行先读入两个数m[i],k[i],m[i]表示有多少个老师开设,k[i]表示占用的时间段数量,接下来m组数据,每组数据有2k个整数,每连续两个表示一节课的时间,第一个数是星期几(1-5),第二个数是时间段(1-6)
输出格式
输出答案
输入输出样例
输入 #1复制
4 1 1 2 1 2 1 2 1 3 1 2 2 3 1 4 2 4 2 5 2 2 2 3 2 4 2 5 2 5 3
输出 #1复制
5
说明/提示
样例解释
一共有4门课程
第一门课程只有一个老师开设,是星期二的第一节
第二门课程有两个老师开设,分别是星期二的第一节和星期三的第一节
第三门课程有两个老师开设,每个老师上两个时间段。第一个老师是星期三的第一节、星期四的第二节;第二个老师是星期四的第二节、星期五的第二节
第四门课程有两个老师开设,每个老师上两个时间段。第一个老师是星期三的第二节、星期四的第二节;第二个老师是星期五的第二节、星期五的第三节
最优方案是选第三门课的第一个老师、第四门课的第二个老师、第一门课
数据范围
对于10%10%的数据,保证n=1n=1。
对于30%30%的数据,保证n⩽5n⩽5。
对于60%60%的数据,保证m=1m=1。
对于100%100%的数据,保证n⩽17,m⩽2,k⩽3n⩽17,m⩽2,k⩽3
代码是一个动态规划的实现,用于解决一个课程安排的问题。代码的主要思路是通过动态规划来计算最大的课程时间安排。
代码的主要部分包括以下几个部分:
-
定义常量和变量:代码中定义了常量MAXN、MAXM和MAXK,分别表示最大的课程数、最大的课程时间段数和最大的课程时间数。变量n表示实际的课程数。
-
定义课程时间表:代码中使用一个二维数组classes来表示每个课程的时间表。classes[i][j]表示第i个课程的第j个时间段,其中时间段是一个pair,包括一个表示天数的整数和一个表示时间的整数。
-
定义动态规划数组:代码中定义了一个动态规划数组dp,dp[mask]表示一个二进制数mask表示的课程安排的最大时间。
-
冲突判断函数:代码中定义了一个冲突判断函数conflict,用于判断一个课程安排是否与已有的课程时间冲突。函数通过遍历已有的课程时间表,判断是否有时间冲突。
-
主函数:主函数中首先读取输入的课程时间表,然后使用动态规划来计算最大的课程时间。通过遍历所有的课程安排的二进制数mask,判断是否有冲突,如果没有冲突,则更新dp数组和最大时间ans。
最后,代码输出最大的课程时间ans。
这段代码的作用是计算课程时间表中的最大课程时间,通过动态规划来解决课程安排的问题。
上代码(70%AC 30%WA)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 17;
const int MAXM = 2;
const int MAXK = 3;
int n;
int m[MAXN], k[MAXN];
vector<pair<int, int>> classes[MAXN][MAXM];
int dp[1 << MAXN];
bool conflict(int mask, int course, int class_idx) {
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
for (auto &time1 : classes[i][0]) {
for (auto &time2 : classes[course][class_idx]) {
if (time1.first == time2.first && time1.second == time2.second) {
return true;
}
}
}
}
}
return false;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> m[i] >> k[i];
for (int j = 0; j < m[i]; j++) {
for (int l = 0; l < k[i]; l++) {
int day, time;
cin >> day >> time;
classes[i][j].push_back({day, time});
}
}
}
memset(dp, 0, sizeof(dp));
int ans = 0;
for (int mask = 0; mask < (1 << n); mask++) {
for (int i = 0; i < n; i++) {
if (!(mask & (1 << i))) {
for (int j = 0; j < m[i]; j++) {
if (!conflict(mask, i, j)) {
int new_mask = mask | (1 << i);
int new_time = dp[mask] + k[i];
dp[new_mask] = max(dp[new_mask], new_time);
ans = max(ans, dp[new_mask]);
}
}
}
}
}
cout << ans << endl;
return 0;
}
提交
于是我删了重写
代码是一个深度优先搜索(DFS)的实现,用于解决课程安排的问题。代码的主要思路是通过DFS来尝试不同的课程安排,然后计算最大的课程时间安排。
代码的主要部分包括以下几个部分:
1. 定义变量和数据结构:代码中定义了变量n表示课程的数量,数组m和k分别表示每门课程的老师数量和时间段数量。结构体node表示课程的时间段。
2. 定义课程时间表:代码中使用了一个二维vector数组v来表示每门课程每个老师的时间段。v[i][j]表示第i门课的第j个老师的时间段,每个时间段用一个node结构体表示。
3. 定义辅助数组:代码中定义了数组a和b来辅助DFS的过程,数组a表示课程安排的情况,数组b用于在DFS过程中的回溯。
4. 定义DFS函数:代码中定义了一个DFS函数,用于尝试不同的课程安排。在DFS过程中,首先尝试不安排当前课程,然后尝试安排当前课程的不同老师的时间段,通过回溯来尝试不同的安排情况。
5. 主函数:主函数中首先读取输入的课程时间表,然后调用DFS函数来计算最大的课程时间。通过DFS的尝试,最后输出最大的课程时间ans。
这段代码的作用是计算课程时间表中的最大课程时间,通过深度优先搜索来解决课程安排的问题。
AC代码
#include <bits/stdc++.h>
using namespace std;
int n;
int m[30],k[30];
struct node {
int day,time;
};
vector<node> v[30][30];//第i门课第j个老师的第k个时间段
int a[30][30];
int b[30][30];
int ans;
void dfs(int x) {
if(x==n+1) {
int cnt=0;
for(int i=1;i<=5;i++) {
for(int j=1;j<=6;j++) {
if(a[i][j]) {
cnt++;
}
}
}
ans=max(ans,cnt);
return;
}
dfs(x+1);
for(int i=1;i<=m[x];i++) {
bool flag=true;
for(int i=1;i<=5;i++) {
for(int j=1;j<=6;j++) {
b[i][j]=a[i][j];
}
}
for(int j=1;j<=k[x];j++) {
if(a[v[x][i][j].day][v[x][i][j].time]==false) {
a[v[x][i][j].day][v[x][i][j].time]=true;
}
else {
flag=false;
break;
}
}
if(!flag) {
for(int j=1;j<=k[x];j++) {
a[v[x][i][j].day][v[x][i][j].time]=b[v[x][i][j].day][v[x][i][j].time];
}
continue;
}
dfs(x+1);
for(int j=1;j<=k[x];j++) {
a[v[x][i][j].day][v[x][i][j].time]=false;
}
}
}
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>m[i]>>k[i];
for(int j=1;j<=m[i];j++) {
v[i][j].push_back({0,0});
for(int kk=1;kk<=k[i];kk++) {
int a,b;
cin>>a>>b;
v[i][j].push_back({a,b});
}
}
}
dfs(1);//正在选第1门课程
cout<<ans<<endl;
return 0;
}