一道状压题,但今天闲来无事又用遗传乱搞了一下。
设了一个DNA数组,DNA[i]记录第i个物品放在哪个组里。适应度是n-这个生物的组数+1.
交配选用的是轮盘赌和单亲繁殖——0.3的几率单点变异。(事实上有性生殖我似乎写不出来……代码量略大)
种群大小开到了400,在vijos上繁殖了2050代,下数据自己测也是对的。
然而只有84分
这究竟是为什么啊 下数据自己测是没错的啊………………
疯了
代码和数据先放到这里,以后再改吧
#include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<algorithm> #include<ctime> inline double random(double from,double to){ return rand()*1.0/RAND_MAX*(to-from)+from; } inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int n; int w[10000],W; int ans=0x7fffffff; struct Creative{ int DNA[19],s[19]; int cnt,score; Creative(){ cnt=0;score=0; memset(s,0,sizeof(s)); } Creative Create(){ Creative New; for(register int i=1;i<=n;++i){ if(New.cnt==0||random(0,1)<=0.5){ New.cnt++; New.DNA[i]=New.cnt; New.s[New.cnt]+=w[i]; } else{ int j,tot=0; Label: tot++; j=random(1,New.cnt); if(New.s[j]+w[i]>W&&tot<=n*2) goto Label; if(!New.s[j]&&tot<=n+10) goto Label; if(tot>=n*2){ New.cnt++; New.DNA[i]=New.cnt; New.s[New.cnt]+=w[i]; continue; } New.DNA[i]=j; New.s[j]+=w[i]; } } if(New.cnt) ans=std::min(ans,New.cnt); New.score=n-New.cnt+1; return New; } }; struct Biome{ Creative e[402]; int tot; void Clear(bool flag){ tot=0; for(int i=1;i<401;++i){ if(flag) e[i]=e[i].Create(); if(e[i].cnt) tot+=e[i].score; if(e[i].cnt==0) i--; } } int Find(){ int sum=0,limit=random(1,tot); for(register int i=1;i<401;++i){ sum+=e[i].score; if(sum>=limit) return i; } return 400; } Creative Multi(int x){ Creative New=e[x]; if(random(0,1)>0.3) return New; int i=random(1,n+1),pos=New.DNA[i]; New.s[pos]-=w[i]; if(!New.s[pos]){ New.cnt--; New.score++; } int j,tot=0; Label: tot++; j=random(1,n); if(New.s[j]+w[i]>W&&tot<=n*2) goto Label; if(!New.s[j]&&tot<=n+10) goto Label; if(tot>=n*2){ New.cnt++; New.DNA[i]=New.cnt; New.score--; New.s[New.cnt]+=w[i]; } else{ New.DNA[i]=j; if(!New.s[j]){ New.cnt++; New.score--; } New.s[j]+=w[i]; ans=std::min(ans,New.cnt); } return New; } }Old,New; inline bool cmp(Creative a,Creative b){ return a.score>b.score; } int main(){ srand(time(NULL)); n=read(),W=read(); for(int i=1;i<=n;++i) w[i]=read(); Old.Clear(1); for(register int T=1;T<=700;++T){ Old.Clear(0); for(register int i=1;i<401;++i) New.e[i]=Old.Multi(Old.Find()); std::sort(Old.e+1,Old.e+401,cmp); std::sort(New.e+1,New.e+401,cmp); for(register int i=1;i<=100;++i) Old.e[300+i]=New.e[i]; } /*for(int i=1;i<=100;++i,printf(" ")){ for(int j=1;j<=n;++j) printf("%d ",Old.e[i].DNA[j]); printf(">>>%d %d",Old.e[i].cnt,Old.e[i].score); }*/ printf("%d",ans); return 0; }
18 100000000
37597832
24520955
100000000
18509980
29141223
20287969
14028193
33097076
12116817
53439913
10216168
32891936
43952038
13463011
4056577
4646046
10153053
37881213
下一个准备用遗传搞的题是猫狗大战。