codeforces 366C

来源:互联网 发布:超级运动会淘宝时间 编辑:程序博客网 时间:2024/06/10 18:25

题意:给出两个数列 A[i] ,B[i];,每个数列n个数和一个k,  要求选出部分数使得     所有 a[i]的和 =所有 k*b[i]的和 ,且 a[i]的和要最大




思路: 

01 背包 以 a[i] -k* b[i]作为每个物品的重量,以a[i]作为价值 ,用容量为0的背包去背 ,

可以拆成两个背包,一个装容量为正的,一个装容量为负的 dp[i]  表示的是恰好装满 容量为 i 的 价值

#include<bits/stdc++.h>using namespace std;const int maxn = 1000000;const int INF = 200000;int a[maxn];int b[maxn];int dp1[maxn];int dp2[maxn];int x1[maxn];int y2[maxn];int x2[maxn];int y1v[maxn];int main(){    int n,k;    scanf("%d%d",&n,&k);    for(int i = 1; i<=n; i++)    {        scanf("%d",&a[i]);    }    for(int  i = 1; i<=n; i++)    {        scanf("%d",&b[i]);        b[i] =  a[i] - k*b[i];    }    int cot1 =1;    int cot2= 1;    int sum1 =0;    int sum2 =0;    int res=0;    for(int i = 1; i<=n; i++)    {        //printf("%d %d\n",a[i],b[i]);        if(b[i]<0)        {            x1[cot1] = a[i];            y1v[cot1]=-b[i];            cot1++;            sum1+=y1v[cot1-1];        }        else if(b[i]>0)        {            x2[cot2]= a[i];            y2[cot2] = b[i];            cot2++;            sum2+=y2[cot2-1] ;        }        if(b[i]==0)            res+=a[i];    }    cot1--;    cot2--;    fill(dp1+1,dp1+1+sum1,-INF);              dp1[0] =0;    int c =0;    for(int i= 1; i<=cot1; i++)    {        for(int j =sum1; j>=y1v[i]; j--)        {            dp1[j] = max(dp1[j],dp1[j-y1v[i]]+x1[i]);        }    }    fill(dp2+1,dp2+1+sum2,-INF);    for(int i = 1; i<=cot2; i++)    {        for(int j = sum2; j>=y2[i]; j--)        {            dp2[j] = max(dp2[j],dp2[j-y2[i]]+x2[i]);        }    }    int ans =0;    int xvd = min(sum1,sum2);    for(int i =1 ; i<=xvd; i++)    {        ans = max(dp2[i]+dp1[i],ans);    }    ans+=res;   // printf("%d\n",ans);    if(ans<=0)        printf("-1\n");    else        printf("%d\n",ans);}


 

0 0