1. 程式人生 > >hdu 2602 Bone Collector【遺傳演算法解01揹包】

hdu 2602 Bone Collector【遺傳演算法解01揹包】

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

暫時就這樣。