超大背包问题


文章用的C++ 我想着用C语言实现

# include <stdio.h>
# define N 40
# define max(a,b)  (a)>(b)?(a):(b)
# define M 1<<(N>>1)
typedef long long LL;
void change(LL *a,LL *b);
void Qsort(LL A[][M],LL left,LL right);//快速排序升序
int search(LL A[],int n,LL key);//查找 A中 的key 病返回 key所在的价值最大值
LL W[N],V[N],C[2][M];
int main(){
    int n,i,j,k,m;
    LL w,sum,sw,sv,num,tv;
   // freopen("AAA.txt","r",stdin);
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
            scanf("%lld%lld",&W[i],&V[i]);
        scanf("%lld",&w);//录入 
        k=n/2;m=1<<k;
        for(i=0;i<m;i++)
        {
            C[0][i]=C[1][i]=0;//初始化 
            for(j=0;j<k;j++)
                if(i>>j&1)
            {
                C[0][i]+=W[j];//枚举前半部分
                C[1][i]+=V[j];
            }
        }
        Qsort(C,0,m-1);//字典序——升序 
        for(j=0,i=1;i<m;i++)
        {
            if(C[1][j]<C[1][i])
            {
                C[0][j]=C[0][i];
                C[1][j++]=C[1][i];//去掉多余元素
            }
        }
        num=j;
        for(sum=0,i=0,m=(n-k),n=1<<m;i<n;i++)//枚举后半部分 并求解
        {
            sw=sv=0;
            for(j=0;j<m;j++)
            {
                if(i>>j&1)
                {
                    sw+=W[k+j];
                    sv+=V[k+j];
                }
            }
            if(sw<=w)
            {
                tv=search(C[0],num,w-sw);
                sum=max(sum,sv+tv);
            }
        }
        printf("%lld\n",sum);
    }
    return 0;
}
void change(LL *a,LL *b){//交换函数
    LL c=*a;
    *a=*b;
    *b=c;
}
void Qsort(LL A[][M],LL left,LL right)//快速排序升序
{
    LL i=left,j=right,temp[2]={A[0][left],A[1][left]};
    if(left>=right)  return;
    while(i!=j)
    {
        while((A[0][j]>temp[0]||A[0][j]==temp[0]&&A[1][j]>=temp[1])&& i<j)j--;
        while((A[0][i]<temp[0]||A[0][i]==temp[0]&&A[1][i]<=temp[1])&& i<j)i++;
        if(i<j)
        {
            change(&A[0][i],&A[0][j]);
            change(&A[1][i],&A[1][j]);
        }
}
if(i!=left)
{
    change(&A[0][left],&A[0][i]);
    change(&A[1][left],&A[1][i]);
}
    Qsort(A,left,i-1);
    Qsort(A,i+1,right);
}
int search(LL A[],int n,LL key)
{
     int L=0,R=n-1,mid,num=0;
    while(L<=R)
    {
        mid=(L+R)>>1;
        if(A[mid]==key) {
            while(mid<n&&A[++mid]==key);
            return C[1][mid-1];
        }
        else if(A[mid]>key)
        R=mid-1;
        else L=mid+1;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值