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程序即可。
暂时就这样。