遗传算法之01背包问题 (C语言实现)

参数说明

n:物品个数
m:种群大小
W:背包容量
其中 a[i] 存储的物品信息 ,g[i]存储基因信息。
maxn :物品数的最大值
maxm :种群数的最大值

注意事项

m 最好是 n 的10倍及其以上,毕竟基因状态数高达 1<<n 种,m 太小的话初始种群如果都不满足 容量之和小于 W 的话,整个种群可能会消失。所以尽量设大一点。

代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 105
#define maxm 1006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
#define PI acos(-1)
#define mod 10007
#define db double
#define auto(i,x) for(int i=head[x];i;i=ed[i].nxt)
ll read(){
    ll x=0,f=1ll;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
     return f*x;
}
int n,m,W;
db xiaorand(db low,db up,db jin){
    db down=min(0.0,low);
    low-=down,up-=down;
    int l=(int)low*jin,r=(int)up*jin;
    int len=r-l+1;
    int num=rand()%len + l;
    return 1.0*num/jin + down;
}
struct node{int w,v;}a[maxn];
struct gen{bitset<maxn>dna;
    int pos;
    bool operator < (const gen &rid)const{
        return pos > rid.pos;
    }
}g[maxm];
void init_population(int x){
    inc(i,1,x)inc(j,1,n)g[i].dna[j]=rand()%2;
}
int f(gen x){
    ll sumv=0,sumw=0;
    inc(i,1,n)if(x.dna[i]){sumv+=a[i].v,sumw+=a[i].w;}
    return sumw <= W ? sumv : -INF;
}
void choose(db sum,int len,int num,int bian,int id){
    db posi=xiaorand(0,1,1000);
    int x=0,y=0;
    inc(i,1,len){
        posi-=1.0*g[i].pos/sum;
        if(posi<=0){x=i;break; }
    }
    posi=xiaorand(0,1,1000);
    inc(i,1,len){
        posi-=1.0*g[i].pos/sum;
        if(posi<=0){y=i;break; }
    }
    gen now=g[x];
    inc(i,1,n){
        if(rand()%2==1){
            now.dna[i]=g[y].dna[i];
            num--;
        }
        if(num==0)break;
    }
    inc(i,1,n){
        if(rand()%2==1){
            now.dna[i]=now.dna[i]^1;
            bian--;
        }
        if(bian==0)break;
    }
    g[id]=now;
}
void kill_and_evaluate(int x){
    inc(i,1,m)g[i].pos=f(g[i]);
    sort(g+1,g+m+1);
    int ccc=m;
    while(g[ccc].pos==-INF)ccc--;
    x=max(x,m-ccc);
    int len=m-x;
    inc(i,1,len)swap(g[i],g[(rand()%i)+1]);
    db sum=0;
    inc(i,1,len)sum+=1.0*g[i].pos;
    inc(i,len+1,m)choose(sum,len,m/2,(m/10)+1,i);
}
int main()
{
    n=read();m=read();W=read();
    inc(i,1,n)a[i].w=read(),a[i].v=read();
    init_population(m);
    inc(i,1,100){
        kill_and_evaluate((m/5)+1);
        int ma=0;
        inc(j,1,m)ma=max(ma,f(g[j]));
        printf("%d : %d\n",i,ma);
    }
    return 0;
}
/*
12 50 25
2 5
2 5
4 8
10 2
2 3
5 7
3 6
8 6
4 7
6 6
3 3
2 1
*/
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值