BZOJ 2336: [HNOI2011]任务调度

随机化乱搞调整

先暴力枚举3的情况,然后贪心出一组1,2的顺序

随机调整顺序,模拟看是否更优,更优则变更为该顺序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int inf=1e9;
const int N=20+5;
int s1[N],tp1,s2[N],tp2;
int a[N],b[N],t[N],n,ans;
bool ch[N];
bool cmp1(int i,int j){
	if(b[i]==b[j])return a[i]<a[j];
	return b[i]>b[j];
}
bool cmp2(int i,int j){
	if(a[i]==a[j])return b[i]<b[j];
	return a[i]>a[j];
}
int calc(){
	int suma=0,sumb=0;
	for(int i=1;i<=tp2;i++)sumb+=b[s2[i]];
	for(int i=1;i<=tp1;i++){
		suma+=a[s1[i]];
		if(suma<=sumb)sumb+=b[s1[i]];
		else sumb=suma+b[s1[i]];
	}
	int sum=sumb;
	suma=sumb=0;
	for(int i=1;i<=tp1;i++)suma+=a[s1[i]];
	for(int i=1;i<=tp2;i++){
		sumb+=b[s2[i]];
		if(sumb<=suma)suma+=a[s2[i]];
		else suma=sumb+a[s2[i]];
	}
	sum=max(sum,suma);
	return sum;
}
void work(){
	tp1=tp2=0;
	for(int i=1;i<=n;i++)if(ch[i])s2[++tp2]=i;else s1[++tp1]=i;
	sort(s1+1,s1+1+tp1,cmp1);
	sort(s2+1,s2+1+tp2,cmp2);
	int sum=calc();
	for(int i=1;i<=2000;i++){
		int a1,a2,b1,b2;
		if(tp1){
			a1=rand()%tp1+1,a2=rand()%tp1+1;
			swap(s1[a1],s1[a2]);
		}
		if(tp2){
			b1=rand()%tp2+1,b2=rand()%tp2+1;
			swap(s2[b1],s2[b2]);
		}
		int tmp=calc();
		if(tmp>=sum){
			if(tp1)swap(s1[a1],s1[a2]);
			if(tp2)swap(s2[b1],s2[b2]);
		}else sum=tmp;
	}
	ans=min(ans,sum);
}
void dfs(int i){
	if(i>n)work();
	else{
		if(t[i]==1)ch[i]=0,dfs(i+1);
		else if(t[i]==2)ch[i]=1,dfs(i+1);
		else{
			ch[i]=0;dfs(i+1);
			ch[i]=1;dfs(i+1);
		}
	}
}
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	srand(541213);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d%d%d",&t[i],&a[i],&b[i]);
	ans=inf;
	dfs(1);
	printf("%d\n",ans);
	return 0;
}


你可能感兴趣的:(BZOJ 2336: [HNOI2011]任务调度)