由于需要顺序的付完N个物品,那么说明具有单调性,二分一下就好了
我们可以思考怎么定义状态
不妨让状态定义为当前最多付了多少物品,这样子就可以保证单调性了
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 17, M = 1 << 17;
const int H = 1e5 + 10;
typedef long long ll;
ll a[H];
ll s[H];
int coin[N];
int n, m;
int dp[M];
int c;
int left_bound(int left )
{
int right = m;
int l = left, r = right;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (s[mid] - s[left - 1] > c)
r = mid - 1;
else if (s[mid] - s[left - 1] == c)
return mid;
else if (s[mid] - s[left - 1] < c)
l = mid;
}
return l;
}
int main()
{
cin >> n >> m;
for (int i = 0;i < n;i++)
cin >> coin[i];
for (int i = 1;i <= m;i++)
cin >> a[i], s[i] = s[i - 1] + a[i];
dp[0] = 0;
for (int i = 0;i < 1 << n;i++)
for (int j = 0;j < n;j++)
if (i >> j & 1)
//for (int k = 0;k < n;k++)
//if (i^(1 << j) >> k & 1)
{
int left = dp[i ^ (1 << j)];
c = coin[j];
int x = left_bound(left+1);
dp[i] = max(dp[i], dp[i ^ (1 << j)] + x-left);
}
int res = -1;
for (int i = 0;i < 1 << n;i++)
{
if (dp[i] >= m)
{
int sum = 0;
for (int j = 0;j < n;j++)
if (!(i >> j & 1)) sum += coin[j];
res = max(res, sum);
}
}
cout << res;
}