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

博客介绍了如何运用遗传算法解决HDU 2602题目的01背包问题,尽管博主提交的C++代码未能通过OJ测试,但分享了遗传算法的基本流程,并提供了Python代码的测试数据下载链接。
摘要由CSDN通过智能技术生成

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 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程序即可。


01背包测试数据地址


暂时就这样。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值