hdu 2602 Bone Collector【遺傳演算法解01揹包】
阿新 • • 發佈:2019-02-02
hdu 2602 Bone Collector
題目分析:01揹包水無坑,由於本篇是用GA解,學習ACM中01揹包問題解法的同學請移步
原連結 。
對遺傳演算法的認識:對生物界遺傳過程進行模擬來解決問題的一種演算法,大體流程如下:遺傳(指定generation數){計算適應度->選擇->交叉->變異}。實際設計演算法時可按需略作調整。
宣告:博主提交oj沒過,全是WA。
以下是C++code
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<algorithm> #define fineN 50 using namespace std; /** 每一組解是一個1*n的陣列,每一位表示第i個物體0不放、1放入 */ int pop_size=890,maxgen=800,pop_pointer=890;//種群最大規模50、迭代次數30、種群當前規模 double te=0.2;//優勢種群前20% int n,v,val[1009],vol[1009]; class Individual { public: int fitness,load; short*strategy; bool overload; Individual(){} Individual(short*s) { //memcpy(strategy,s,n*sizeof(short)); strategy=new short(1009); for(int i=0;i<n;i++) { strategy[i]=s[i]; } load=fitness=0; overload=false; cal_fitnld(); } void cal_fitnld() {//計算fitness,多出的load按fineN倍懲罰 fitness=load=0; for(int i=0;i<n;i++) { fitness+=strategy[i]?val[i]:0; load+=strategy[i]?vol[i]:0; //printf("第%d個%s\n",i,strategy[i]?"裝":"不裝"); } if(load>v) { //printf("超載:load=%d, v=%d\n",load,v); fitness-=(load-v)*fineN; overload=true; } } /*void mutation() { if((rand()%10)<2)//判斷是否變 { int flag=rand()%n; if(strategy[flag]==0) {//計算適應度 fitness+=val[flag]; load+=vol[flag]; } strategy[flag]=1-strategy[flag];//變 } }*/ }; int cmp(Individual a,Individual b) { return a.fitness>b.fitness; }/* short*shtcpy(short*b) { short a[100]; for(int i=0;i<n;i++) { a[i]=b[i]; } return a; } char*chrom2str(short*a) { char ret[100]; for(int i=0;i<n;i++) { ret[i]=a[i]+'0'; } ret[n]=0; return ret; }*/ int main() { Individual inque[1009]; srand((unsigned)time(NULL)); int t; short s1[1009],s2[1009]; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&v); for(int i=0;i<n;i++) { scanf("%d",val+i); } for(int i=0;i<n;i++) { scanf("%d",vol+i); } //初始化種群 for(int i=0;i<pop_size;i++) { for(int j=0;j<n;j++) { s1[j]=rand()%2; } inque[i]=*(new Individual(s1)); } //進化開始 for(int i=0;i<maxgen;i++) { //選擇==丟棄劣勢種群 pop_pointer=pop_size*te; //交叉變異 while(pop_pointer<pop_size) { if(rand()%2)//交叉 {//交叉概率50%,其中10%是兩位交叉 int fc=rand()%pop_pointer,sc=rand()%pop_pointer;//first or second chrom int place=rand()%n; /*for(int j=0;j<n;j++) { s1[j]=inque[fc].strategy[j]; s2[j]=inque[sc].strategy[j]; }*/ memcpy(s1,inque[fc].strategy,n*sizeof(short)); memcpy(s2,inque[sc].strategy,n*sizeof(short)); //s1=shtcpy(inque[fc].strategy); //s2=shtcpy(inque[sc].strategy); if(inque[fc].strategy[place]!=inque[sc].strategy[place]) { s1[place]=1-s1[place]; s2[place]=1-s2[place]; } if(rand()%10==0) { place=rand()%n; s1[place]=1-s1[place]; s2[place]=1-s2[place]; } inque[pop_pointer++]=*(new Individual(s1)); inque[pop_pointer++]=*(new Individual(s2)); //printf("交叉:pop_pointer=%d\n",pop_pointer); } else//變異 { int chrom=rand()%pop_pointer,place=rand()%n; //printf("copy前:s1=%s,chrom=%s\n",chrom2str(s1),chrom2str(inque[chrom].strategy)); //s1=shtcpy(inque[chrom].strategy); /*for(int j=0;j<n;j++) { s1[j]=inque[chrom].strategy[j]; }*/ memcpy(s1,inque[chrom].strategy,n*sizeof(short)); //printf("copy後:s1=%s,chrom=%s\n",chrom2str(s1),chrom2str(inque[chrom].strategy)); s1[place]=1-s1[place]; //printf("變異後:s1=%s,chrom=%s\n",chrom2str(s1),chrom2str(inque[chrom].strategy)); inque[pop_pointer++]=*(new Individual(s1));//變 } } sort(inque,inque+pop_size,cmp); /*printf("\nfit list:"); for(int j=0;j<pop_size;j++) { printf("\t%d",inque[j].fitness); } putchar('\n');*/ } /*printf("\n結果:fitness1=%d\n",inque[0].fitness); for(int i=0;i<n;i++) { printf("%c\n",inque[0].strategy[i]+'0'); }*/ printf("%d\n",inque[0].fitness); }//斷點設定 return 0; }
C++……,請執行出錯的同學在return 0;上一行標記處設定斷點除錯執行,別問我為什麼,我也不知道。如有大神路過還請不吝賜教。
寫這些東西果斷還是應該用python的嘛
# coding:utf-8 import copy import random class GApackageSolution: #此類解決用GA解揹包問題 maxgen=35 #最大代數 pop_size=120 #種群規模 n=0 #物品總數 v=0 #揹包容量 te=0.2 #top elite佔比 population=[] #種群 class Individual: fineN=18 #懲罰係數,用於超重懲罰 val=[] #物品價值 vol=[] #物品體積 def __init__(self,c): self.chrom=copy.deepcopy(c) self.fitness=0 self.load=0 #print len(c),len(self.val),len(self.vol) for i in range(len(c)): self.fitness+=self.val[i]if c[i]==1 else 0 self.load+=self.vol[i]if c[i]==1 else 0 pass if self.load>v:self.fitness-=self.fineN*(self.load-v) return def do_cross(self,c1,c2,cp1,cp2,place,pop): if place==0: chrom1=[cp2]+pop[c1].chrom[1:] chrom2=[cp1]+pop[c2].chrom[1:] pass else: chrom1=pop[c1].chrom[:place-1]+[cp2]+pop[c1].chrom[place:] chrom2=pop[c2].chrom[:place-1]+[cp1]+pop[c2].chrom[place:] pass return chrom1,chrom2 def cross(self): #print 'cross called' pop=self.population c1=random.randint(0,len(pop)-1) c2=random.randint(0,len(pop)-1) place=random.randint(0,n-1) cp1=pop[c1].chrom[place] cp2=pop[c2].chrom[place] #print 'chrom1=',pop[c1].chrom,'chrom2=',pop[c2].chrom,'place=',place #print pop[c1].chrom[:place-1],[cp2],pop[c1].chrom[place:] chrom1,chrom2=self.do_cross(c1,c2,cp1,cp2,place,pop) if random.randint(0,2)==0: place=random.randint(0,n-1) cp1=chrom1[place] cp2=chrom2[place] chrom1,chrom2=self.do_cross(c1,c2,cp1,cp2,place,pop) #print len(chrom1),len(chrom2) pass #print chrom1,chrom2 self.population.append(self.Individual(chrom1)) self.population.append(self.Individual(chrom2)) return def do_mutation(self,ochrom,place): if place==0: xchrom=[1-ochrom[place]]+ochrom[1:] pass else: xchrom=ochrom[:place-1]+[1-ochrom[place]]+ochrom[place:] pass return xchrom def mutation(self): #print 'mutation called' pop=self.population c=random.randint(0,len(pop)-1) place=random.randint(0,n-1) ochrom=pop[c].chrom #original chrom原始染色體 #print 'ochrom=',ochrom,'place=',place #print ochrom[:place-1],[1-ochrom[place]],ochrom[place:] xchrom=self.do_mutation(ochrom,place) #print xchrom self.population.append(self.Individual(xchrom)) return def run(self): for k in range(self.maxgen): self.population=self.population[:int(self.te*self.pop_size)] for i in range(len(self.population)): print 'strategy:',i,self.population[i].chrom,'fitness=',\ self.population[i].fitness #剔除劣勢種群 while len(self.population)<=self.pop_size:#交叉變異補回來 if(random.randint(0,1)==0): #print 'mutation call' self.mutation() pass else: #print 'cross call' self.cross() pass pass self.population.sort(lambda x,y:cmp(y.fitness,x.fitness)) pass ret='strategy:' for i in range(self.n): ret=ret+str(self.population[0].chrom[i]) return ret+'\nfitness:'+str(self.population[0].fitness) def __init__(self,n,v,val,vol): self.n=n self.v=v self.Individual.val=val self.Individual.vol=vol for i in range(self.pop_size): c=[] for j in range(n): c.append(random.randint(0,1)) self.population.append(self.Individual(c)) #print c pass return if __name__=='__main__': print 'Which one would you like to test?' filenum=raw_input('Please input a number between 0-9.\n') fp=open('beibao'+filenum+'.in') line=fp.readline() line=line.strip() line=line.split(' ') print line v=int(line[0]) n=int(line[1]) val=[] vol=[] for line in fp.readlines(): line=line.strip() line=line.split() vol.append(int(line[0])) val.append(int(line[1])) pass obj=GApackageSolution(n,v,val,vol) print obj.run()
前幾天系統崩潰,程式碼沒了,這一版是後寫的,所以註釋略少,見諒
注意,不要用hdu 2602的輸入,python版的輸入格式與那個不符,我已經上傳了資料壓縮包,地址如下。輸入就將那個壓縮包裡的檔案解壓到程式檔案旁,執行python程式即可。
暫時就這樣。