考虑$P=0$,由于$T-\sum_{i=1}^{m}s_{i}\le 40$,因此一个第$i$个分类中最多得到$s_{i}+42$的学分,可以对每一类分别背包
暴力背包复杂度为$o(n^{2})$,但背包实际用到的部分只有$o(40)$个位置,因此考虑直接求某个体积的答案
先枚举$3$的个数,那么问题相当于求体积为$\{1,2\}$的答案,可以将相邻两个1看作一个2来贪心,预处理出两类的前缀和,再对体积的奇偶性分类讨论
时间复杂度:预处理$o(n\log n+40n)$,合并$o(40^{2}m)$
当$P=12$,先对与$P$无关的分类按上述方式处理,那么剩下的问题就有$m\le 12$
对于这些分类,先求出所有没有限制的课程的结果(注意这里的范围要到$[s_{i}-36,s_{i}+42]$),然后$o(2^{P})$暴力枚举这些课程是否选择,复杂度$o(2^{P}40^{2}m+76n)$
有两个小问题:1.有一组数据不满足$T\ge \sum_{i=1}^{m}s_{i}$,因此差值需要对0取min;2.最终的和有可能超过$\sum_{i=1}^{m}s_{i}+42$,但下标不能太大(否则复杂度不对),将下标对$T-\sum_{i=1}^{m}s_{i}$取min即可

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 50004
4 #define oo 0x3f3f3f3f
5 map<int,int>mat[N];
6 map<int,int>::iterator it;
7 vector<int>vo,ve,w[N],c[N],v[N][4];
8 int V,n,m,x,y,ans,a[N],s[N],vis[105],p[105],sum[105][105],g[105],f[105],ff[105][105],dp[105];
9 void init(int k){
10 vo.clear();
11 for(int i=0;i+1<v[k][1].size();i+=2)vo.push_back(v[k][1][i]+v[k][1][i+1]);
12 for(int i=0;i<v[k][2].size();i++)vo.push_back(v[k][2][i]);
13 sort(vo.begin(),vo.end());
14 for(int i=0;i+1<vo.size();i++)vo[i+1]+=vo[i];
15 ve.clear();
16 for(int i=1;i+1<v[k][1].size();i+=2)ve.push_back(v[k][1][i]+v[k][1][i+1]);
17 for(int i=0;i<v[k][2].size();i++)ve.push_back(v[k][2][i]);
18 sort(ve.begin(),ve.end());
19 for(int i=0;i+1<ve.size();i++)ve[i+1]+=ve[i];
20 }
21 int query_12(int k,int x){
22 if (x<0)return oo;
23 if (x%2==0){
24 if (x==0)return 0;
25 if (vo.size()<x/2)return oo;
26 return vo[x/2-1];
27 }
28 if (!v[k][1].size())return oo;
29 if (x==1)return v[k][1][0];
30 if (ve.size()<x/2)return oo;
31 return ve[x/2-1]+v[k][1][0];
32 }
33 int query_123(int k,int x){
34 int s=0,ans=query_12(k,x);
35 for(int i=0;i<v[k][3].size();i++){
36 s+=v[k][3][i];
37 ans=min(ans,s+query_12(k,x-3*(i+1)));
38 }
39 return ans;
40 }
41 void merge(){
42 memset(ff[0],oo,sizeof(ff[0]));
43 for(int i=0;i<=42;i++)
44 for(int j=0;j<=42;j++)ff[0][min(i+j,s[0])]=min(ff[0][min(i+j,s[0])],f[i]+dp[j]);
45 memcpy(dp,ff[0],sizeof(dp));
46 }
47 void dfs(int k){
48 if (k>V){
49 int tot=0;
50 for(int i=1;i<=V;i++)
51 for(int j=1;j<=V;j++)
52 if ((vis[i])&&(vis[j])){
53 if (sum[i][j]==oo)return;
54 tot+=sum[i][j];
55 }
56 for(int i=1;i<=p[0];i++)
57 for(it=mat[p[i]].begin();it!=mat[p[i]].end();it++)
58 if (vis[(*it).second])tot+=c[p[i]][(*it).first];
59 memcpy(dp,g,sizeof(g));
60 for(int i=1;i<=p[0];i++){
61 int ss=0;
62 for(it=mat[p[i]].begin();it!=mat[p[i]].end();it++)
63 if (vis[(*it).second])ss+=w[p[i]][(*it).first];
64 for(int j=0;j<=42;j++)f[j]=ff[i][j+36-ss];
65 merge();
66 }
67 for(int i=s[0];i<=42;i++)ans=min(ans,tot+dp[i]);
68 return;
69 }
70 vis[k]=0;
71 dfs(k+1);
72 vis[k]=1;
73 dfs(k+1);
74 }
75 int main(){
76 scanf("%d%d",&n,&s[0]);
77 for(int i=1;i<=n;i++){
78 scanf("%d%d",&a[i],&s[i]);
79 for(int j=1;j<=a[i];j++){
80 scanf("%d%d",&x,&y);
81 w[i].push_back(x);
82 c[i].push_back(y);
83 v[i][x].push_back(y);
84 }
85 for(int j=1;j<4;j++)sort(v[i][j].begin(),v[i][j].end());
86 s[0]-=s[i];
87 }
88 s[0]=max(s[0],0);
89 scanf("%d",&m);
90 for(int i=1;i<=m;i++){
91 int p,x1,y1,x2,y2,cc;
92 scanf("%d%d%d%d%d",&p,&x1,&y1,&x2,&y2);
93 if (p==3)cc=oo;
94 else{
95 scanf("%d",&cc);
96 if (p==1)cc=-cc;
97 }
98 if (!mat[x1][y1-1])mat[x1][y1-1]=++V;
99 if (!mat[x2][y2-1])mat[x2][y2-1]=++V;
100 sum[mat[x1][y1-1]][mat[x2][y2-1]]=cc;
101 }
102 memset(dp,oo,sizeof(dp));
103 dp[0]=0;
104 for(int i=1;i<=n;i++)
105 if (!mat[i].size()){
106 init(i);
107 for(int j=0;j<=42;j++)f[j]=query_123(i,j+s[i]);
108 merge();
109 }
110 else{
111 p[++p[0]]=i;
112 for(it=mat[i].begin();it!=mat[i].end();it++){
113 x=(*it).first;
114 v[i][w[i][x]].erase(lower_bound(v[i][w[i][x]].begin(),v[i][w[i][x]].end(),c[i][x]));
115 }
116 init(i);
117 for(int j=-36;j<=42;j++)ff[p[0]][j+36]=query_123(i,j+s[i]);
118 }
119 memcpy(g,dp,sizeof(g));
120 ans=oo;
121 dfs(1);
122 if (ans>=oo)ans=-1;
123 printf("%d",ans);
124 }

[loj3331]选课的更多相关文章

  1. 从零开始学Python06作业思路:学生选课系统

    一,作业要求 选课系统: 管理员: 创建老师:姓名.性别.年龄.资产 创建课程:课程名称.上课时间.课时费.关联老师 学生:用户名.密码.性别.年龄.选课列表[].上课记录{课程1:[di,a,]} ...

  2. python之选课系统详解[功能未完善]

    作业需求 思路:1.先写出大体的类,比如学校类,学生类,课程类--   2.写出类里面大概的方法,比如学校类里面有创建讲师.创建班级-- 3.根据下面写出大致的代码,并实现其功能       遇到的困 ...

  3. 第一章-第六题(帮人抢票,帮人选课这些软件是否合法 你怎么看?)--By梁旭晖

    我觉得这些软件是合法的,符合道德规范的. 计算机当初设计的初衷就是简化甚至替代人类的工作.而软件作为计算机硬件的驱动着,其设计就是体现这些原则. 现在互联网上的订票,选课类型的网站还是有很多的,比如: ...

  4. Python开发程序:选课系统-改良版

    程序名称: 选课系统 角色:学校.学员.课程.讲师要求:1. 创建北京.上海 2 所学校2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开3. ...

  5. SQL Server 【附】创建"商品管理数据库"、"学生选课数据库"的SQL语句

    附:(创建“商品管理数据库”的SQL语句) --建立"商品管理数据库"数据库-- create database 商品管理数据库 on(name='商品管理数据库_m', file ...

  6. BFS、DFS与选课问题(拓扑排序)

    1选课问题 Leetcode上有这样一道题:有代号0,1,2……n-1的n门课程.其中选择某些课程需要另一些课程作为前提条件.用一组pair来表示这些条件:[1,0],[1,2],表示如果要选修课程1 ...

  7. Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]

    题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...

  8. python实现学生选课系统 面向对象的应用:

    一.要求: 选课系统 管理员: 创建老师:姓名.性别.年龄.资产 创建课程:课程名称.上课时间.课时费.关联老师 使用pickle保存在文件 学生: 学生:用户名.密码.性别.年龄.选课列表[].上课 ...

  9. Python开发程序:选课系统

    本节作业: 选课系统 角色:学校.学员.课程.讲师要求:1. 创建北京.上海 2 所学校2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开3. ...

随机推荐

  1. JUC多线程之ThreadPoolExecutor类任务执行流程

    ThreadPoolExecutor类: ThreadPoolExecutor是我们最常用的一个线程池类,它实现了AbstractExecutorService接口.首先来看一下它的构造器及相关关键变 ...

  2. ❤️这应该是Postman最详细的中文使用教程了❤️(新手使用,简单明了)

    ️这应该是Postman最详细的中文使用教程了️(新手使用,简单明了) 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进 ...

  3. 禅道开源版 Ldap认证插件开发

    禅道开源版-Ldap插件开发 背景 由于开源版无法使用ldap认证,所以在此分享一下自己开发禅道的ldap开发过程,希望对你有所帮助. 简单说一下这个插件的功能: 1.跳过原有禅道认证,使用ldap认 ...

  4. css单位px,em,rem区别

    在css中单位长度用的最多的是px.em.rem,这三个的区别是: px是固定的像素,一旦设置了就无法因为适应页面大小而改变. em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定 ...

  5. [技术博客] Django中文件的保存与访问

    [技术博客] Django中文件的保存与访问 在TextMarking项目开发中,数据库需要保存用户上传的文本文档. 原型设计:用户点击上传文本->保存文本->文本发送到后端保存为文件. ...

  6. 软件工程个人博客作业-软件案例分析:VS与VS Code

    项目 内容 本作业属于北航 2020 年春软件工程 博客园班级连接 本作业是本课程个人项目作业 作业要求 我在这个课程的目标是 提高软件开发能力.团队协作能力 这个作业在哪个具体方面帮助我实现目标 提 ...

  7. BUAA2020软工作业(四)——结对项目

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 进一步提高自己的编码能力,工程能力,团队协作能力 这个作业在哪 ...

  8. golang常用库:cli命令行/应用程序生成工具-cobra使用

    golang常用库:cli命令行/应用程序生成工具-cobra使用 一.Cobra 介绍 我前面有一篇文章介绍了配置文件解析库 Viper 的使用,这篇介绍 Cobra 的使用,你猜的没错,这 2 个 ...

  9. (转)linux下错误的捕获:errno和strerror的使用,以及perror和strerror的区别

    经常在调用linux 系统api 的时候会出现一些错误,比方说使用open() write() creat()之类的函数有些时候会返回-1,也就是调用失败,这个时候往往需要知道失败的原因.这个时候使用 ...

  10. C++常见STL介绍

    栈 :FILO 栈(stack)又名堆栈,它是一种线性表,是一个后进先出的数据结构. 使用时须加上头文件:#include<stack> 允许进行插入和删除操作的一端称为栈顶(top),另 ...