题目大意:给定一个账单序列,每张消费卡可以支付连续的一段账单,问最少用价值多少的消费卡能支付所有账单
一眼状压DP,f[i]表示i状态下最远能付到哪张账单,然后预处理一下每张消费卡从每张账单开始最远能付到哪,转移一下就行了
时间复杂度O(2^K*N)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
int v[17],a[N];
int g[17][N];
int f[N];
int k,n,tot=0;
void pre()
{
int i,j;
for(i=0;i<k;i++)
{
int now=0,h=0;
for(j=1;j<=n;j++)
{
now+=a[j];
while(now>v[i])
{
now-=a[h];
g[i][h]=j-1;
h++;
}
}
for(j=h;j<=n;j++)
g[i][j]=n;
}
}
int main()
{
scanf("%d%d",&k,&n);
int i,j,l,o,p,x,y;
for(i=0;i<k;i++)
scanf("%d",&v[i]),tot+=v[i];
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
pre();
int anss=707185547;
for(j=1;j<=(1<<k)-1;j++)
{
for(i=0;i<k;i++)
if(j&(1<<i))
f[j]=max(f[j],g[i][f[j-(1<<i)]+1]);
if(f[j]>=n)
{
int ans=0;
for(i=0;i<k;i++)
if(j&(1<<i))
ans+=v[i];
anss=min(anss,ans);
}
}
if(anss==707185547) puts("-1");
else printf("%d",tot-anss);
}