您的位置:首页 > 其它

超大背包问题

2018-03-06 18:57 169 查看




文章用的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
,V
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: