题目大意:

给出两个序列,询问是否存在一种选下标的方案使得:

也就说a和b要么一起拿要么一起不拿

题目思路:

因为状态被绑定,所以可以直接考虑他们绑在一起

假设:

那么必然有:

所以说可以让b序列每个数都,之后令

也就说问题转换为了,求取的物品重量为0时,最大权值

这样就可以直接01背包了。

考虑到出现负数的情况,整体增加一个偏移量即可

Code:

/*** keep hungry and calm CoolGuang!  ***/
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 2e5+700;
const int M = 1e6+8;
const ll mod= 1e9+7;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int dp[105][maxn];
int a[maxn],b[maxn];
ll base = 10000;
int main(){
    read(n);read(m);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++){
        read(b[i]);
        b[i] *= m;
    }
    memset(dp,-1,sizeof(dp));
    dp[0][base] = 0; 
    for(int i=1;i<=n;i++){
        for(int k=0;k<=3*base;k++) dp[i][k] = dp[i-1][k]; 
           int w = b[i] - a[i];
           for(int k=w;k<=3*base;k++)
               if(~dp[i-1][k-w])
                   dp[i][k] = max(dp[i-1][k-w]+a[i],dp[i][k]);
    }
    di(dp[n][base]==0?-1:dp[n][base]);
    return 0;
}