hdu 2602 Bone Collector【遗传算法解01背包】

来源:互联网 发布:u盘修复软件 编辑:程序博客网 时间:2024/06/06 18:53

hdu 2602 Bone Collector

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602

题目分析:01背包水无坑,由于本篇是用GA解,学习ACM中01背包问题解法的同学请移步 原链接 。

对遗传算法的认识:对生物界遗传过程进行模拟来解决问题的一种算法,大体流程如下:遗传(指定generation数){计算适应度->选择->交叉->变异}。实际设计算法时可按需略作调整。

声明:博主提交oj没过,全是WA

以下是C++code

#include<stdio.h>#include<stdlib.h>#include<time.h>#include<algorithm>#define fineN 50using 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-8import copyimport randomclass 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        returnif __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程序即可。


01背包测试数据地址


暂时就这样。



0 0