[loj3331]选课

考虑$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 }
View Code

 

posted @ 2020-08-21 12:33  PYWBKTDA  阅读(138)  评论(0编辑  收藏  举报