P3212 [HNOI2011] 任务调度

题意

nnn 个任务,第 iii 个任务需要在 AAA 机器上执行 aia_iai 时间,在 BBB 机器上执行 bib_ibi 时间,每个任务有一个类型 tit_iti。

  1. 类型 111
    需要先在 AAA 机器上执行,再在 BBB 机器上执行。
  2. 类型 222
    需要现在 BBB 机器上执行,再在 AAA 机器上执行。
  3. 类型 333
    无要求。

问把所有任务完成的最短时间。

n≤20n\le20n≤20。

思路

先暴力枚举出所有 ti=3t_i=3ti=3 的物品先在 AAA 执行还是现在 BBB 执行。

现在问题变成了:nnn 个任务,每个任务要先在 A/BA/BA/B 上执行,问把全部任务执行完成的总时间。

显然,最优情况是 max⁡(∑ai,∑bi)\max(\sum a_i,\sum b_i)max(∑ai,∑bi),但是有时候取不到。设初始在 AAA 的物品集合为 SAS_ASA,初始在 BBB 的物品集合为 SBS_BSB,不妨设 ∑i∈SAai≥∑i∈SBbi\sum_{i\in S_A}a_i\ge\sum_{i\in S_B}b_i∑i∈SAai≥∑i∈SBbi,那么 AAA 机器工作的时间一定是满的,即从 000 工作到 ∑ai\sum a_i∑ai,考虑 BBB 机器。设 fsf_sfs 表示 AAA 机器完成了 sss 中的物品 (s⊂SA)(s\subset S_A)(s⊂SA),BBB 机器最少有多久没工作。显然,当 ∑i∈sai≤∑i∈SBbi\sum_{i\in s}a_i\le\sum_{i\in S_B}b_i∑i∈sai≤∑i∈SBbi 时,fsf_sfs 为 000,否则枚举上一个完成的物品,进行转移。

时间复杂度未知,估算一下大概是 2×1082\times10^82×108,但是跑不满。

代码

cpp 复制代码
// Problem: P3212 [HNOI2011] 任务调度
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3212
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T&x){
        x=0;char c=getchar();bool f=0;
        while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
        f?x=-x:0;
    }
    template<typename T>
    inline void write(T x){
        if(x==0){putchar('0');return ;}
        x<0?x=-x,putchar('-'):0;short st[50],top=0;
        while(x) st[++top]=x%10,x/=10;
        while(top) putchar(st[top--]+'0');
    }
    inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
    inline void write(char c){putchar(c);}
    inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
    inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
    template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
    template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
    template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const int maxn=30,inf=1000000000;
int n,A[maxn],B[maxn],t[maxn],cnt3,cnt_a,cnt_b,f[1048576],sum2a[1048576],sum2b[1048576];
short hv[1048576][21],cnt_hv[1048576];
struct node{int a,b;}a[maxn],b[maxn];
int calc(){
    int suma=0,sumb=0;
    for(int i=1;i<=cnt_a;i++) suma+=a[i].a;
    for(int i=1;i<=cnt_b;i++) sumb+=b[i].b;
    if(suma<sumb){
        swap(a,b);
        swap(cnt_a,cnt_b);
        swap(suma,sumb);
        for(int i=1;i<=cnt_a;i++) swap(a[i].a,a[i].b);
        for(int i=1;i<=cnt_b;i++) swap(b[i].a,b[i].b);
    }
    for(int s=0;s<(1<<cnt_a);s++){
        sum2a[s]=sum2b[s]=0;
        for(int i=1;i<=cnt_hv[s];i++) sum2a[s]+=a[hv[s][i]].a;
        for(int i=1;i<=cnt_hv[s];i++) sum2b[s]+=a[hv[s][i]].b;
    }
    for(int s=0;s<(1<<cnt_a);s++){
        int sum=sum2a[s];
        if(sum<=sumb){f[s]=0;continue;}
        f[s]=inf;
        for(int ii=1;ii<=cnt_hv[s];ii++){
            int i=hv[s][ii];
            int lt=(s^(1<<i-1));
            int tb=sumb+sum2b[lt]+f[lt];
            int ta=sum;
            f[s]=min(f[s],f[lt]+max(0,ta-tb));
        }
    }
    int sumalla=0,sumallb=0;
    for(int i=1;i<=cnt_a;i++) sumalla+=a[i].a,sumallb+=a[i].b;
    for(int i=1;i<=cnt_b;i++) sumalla+=b[i].a,sumallb+=b[i].b;
    return max(sumalla,f[(1<<cnt_a)-1]+sumallb);
}
signed main(){
    for(int i=0;i<1048576;i++)
        for(int j=1;j<=20;j++) if(i&(1<<j-1)) hv[i][++cnt_hv[i]]=j;
    read(n);
    for(int i=1;i<=n;i++) read(t[i],A[i],B[i]),cnt3+=(t[i]==3);
    int ans=inf;
    for(int i=0;i<(1<<cnt3);i++){
        int nwcnt=0;
        cnt_a=cnt_b=0;
        for(int j=1;j<=n;j++){
            if(t[j]==1) a[++cnt_a]={A[j],B[j]};
            else if(t[j]==2) b[++cnt_b]={A[j],B[j]};
            else{
                if(i&(1<<nwcnt)) a[++cnt_a]={A[j],B[j]};
                else b[++cnt_b]={A[j],B[j]};
                nwcnt++;
            }
        }
        ans=min(ans,calc());
    }
    write(ans);
    return 0;
}
相关推荐
oyguyteggytrrwwwrt2 小时前
自制交叉线路识别算法
算法
手写码匠2 小时前
华为云Flexus+DeepSeek征文|Dify 多智能体协同编排实战:R1 规划 + V3 执行,构建企业 Agent 团队
人工智能·深度学习·算法·aigc
晓天衡宇•评测社区3 小时前
FSR-Bench 前沿科学推理榜单发布:GPT-5.5 居首,“会推理”未必“能答对”
算法
程序喵大人4 小时前
【C++进阶】STL算法与函数对象 - 02 sort为什么需要随机访问迭代器
开发语言·c++·算法
hanlin034 小时前
动态规划专练:力扣第121、122题
笔记·算法·leetcode
To_OC4 小时前
LC 74 搜索二维矩阵:换皮的二分查找,我居然一开始没看出来
javascript·算法·leetcode
文心快码BaiduComate4 小时前
文心快码荣获“中国优秀软件产品”,实力再获国家级认可
算法·代码规范
玖玥拾4 小时前
LeetCode 189 轮转数组
算法·leetcode
ZhangShao06074 小时前
题解:CF2249B
c++·算法
小玮看世界4 小时前
[Python]线段树与二分法
数据结构·算法