BZOJ2336: [HNOI2011]任务调度

BZOJ2336: [HNOI2011]任务调度

Description


题解Here!

 

这个题一眼看去贪心对吧。。。
我们枚举第3种任务先跑$A$还是$B$。
这样是$2^{20}$的。
但是有时候贪心可能并不是对的。。。
所以我们可以在贪心基础上加上随机化。
大力随机交换$A,B$机器任务执行的先后顺序,贪心计算时间。
如果更优就保存,大概每次随机$2000$次够了。
模拟退火好像被卡常了,不清楚。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 25
using namespace std;
int n,ans=2147483646;
int top_A,top_B,que_A[MAXN],que_B[MAXN];
bool flag[MAXN];
struct Task{
    int t,a,b;
}a[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline bool cmp1(const int &p,const int &q){
    if(a[p].b==a[q].b)return a[p].a<a[q].a;
    return a[p].b>a[q].b;
}
inline bool cmp2(const int &p,const int &q){
    if(a[p].a==a[q].a)return a[p].b<a[q].b;
    return a[p].a>a[q].a;
}
int calculate(){
    int sum_A=0,sum_B=0,s=0;
    for(int i=1;i<=top_A;i++)sum_A+=a[que_A[i]].a;
    for(int i=1;i<=top_B;i++){
        sum_B+=a[que_B[i]].b;
        if(sum_A>sum_B)sum_A+=a[que_B[i]].a;
        else sum_A=sum_B+a[que_B[i]].a;
    }
    s=max(sum_A,sum_B);
    sum_A=sum_B=0;
    for(int i=1;i<=top_B;i++)sum_B+=a[que_B[i]].b;
    for(int i=1;i<=top_A;i++){
        sum_A+=a[que_A[i]].a;
        if(sum_B>sum_A)sum_B+=a[que_A[i]].b;
        else sum_B=sum_A+a[que_A[i]].b;
    }
    s=max(s,max(sum_A,sum_B));
    return s;
}
void solve(){
    top_A=top_B=0;
    for(int i=1;i<=n;i++){
        if(flag[i])que_B[++top_B]=i;
        else que_A[++top_A]=i;
    }
    sort(que_A+1,que_A+top_A+1,cmp1);
    sort(que_B+1,que_B+top_B+1,cmp2);
    int s=calculate();
    for(int cases=1;cases<=2000;cases++){
        int a1,a2,b1,b2;
        if(top_A){
            a1=rand()%top_A+1;a2=rand()%top_A+1;
            swap(que_A[a1],que_A[a2]);
        }
        if(top_B){
            b1=rand()%top_B+1;b2=rand()%top_B+1;
            swap(que_B[b1],que_B[b2]);
        }
        int now=calculate();
        if(now<s)s=now;
        else{
            if(top_A)swap(que_A[a1],que_A[a2]);
            if(top_B)swap(que_B[b1],que_B[b2]);
        }
    }
    ans=min(ans,s);
}
void dfs(int x){
    if(x>n){
        solve();
        return;
    }
    if(a[x].t==1){flag[x]=false;dfs(x+1);}
    else if(a[x].t==2){flag[x]=true;dfs(x+1);}
    else{
        flag[x]=false;dfs(x+1);
        flag[x]=true;dfs(x+1);
    }
}
int main(){
    srand(2002);
    n=read();
    for(int i=1;i<=n;i++){a[i].t=read();a[i].a=read();a[i].b=read();}
    dfs(1);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-08-16 16:41  符拉迪沃斯托克  阅读(245)  评论(0编辑  收藏  举报
Live2D