c++题目_T318306 上课

题目描述

新学期到了,白兔又要开始选课了。

一周有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

代码是一个动态规划的实现,用于解决一个课程安排的问题。代码的主要思路是通过动态规划来计算最大的课程时间安排。

代码的主要部分包括以下几个部分:

  1. 定义常量和变量:代码中定义了常量MAXN、MAXM和MAXK,分别表示最大的课程数、最大的课程时间段数和最大的课程时间数。变量n表示实际的课程数。

  2. 定义课程时间表:代码中使用一个二维数组classes来表示每个课程的时间表。classes[i][j]表示第i个课程的第j个时间段,其中时间段是一个pair,包括一个表示天数的整数和一个表示时间的整数。

  3. 定义动态规划数组:代码中定义了一个动态规划数组dp,dp[mask]表示一个二进制数mask表示的课程安排的最大时间。

  4. 冲突判断函数:代码中定义了一个冲突判断函数conflict,用于判断一个课程安排是否与已有的课程时间冲突。函数通过遍历已有的课程时间表,判断是否有时间冲突。

  5. 主函数:主函数中首先读取输入的课程时间表,然后使用动态规划来计算最大的课程时间。通过遍历所有的课程安排的二进制数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;
}

 

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值