给你n个数,,让你将其分解成m-1连续的偶数段,,每段的一半为半段重,,求解最重的的半段的最小的值,
看到这个题意不难想到要用二分法,,但是在用二分法的时候我们却很难想到DP也可以用在其中,,
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 40005
#define inf 0x3f3f3f
int s[maxn];
int dp[maxn][2];
int n,m,k;
int check(int x)
{
memset(dp,inf ,sizeof(dp));
dp[0][0]=0;
for(int i=2;i<=n;i++)
{
for(int j=1;j<k&&i-j*2>=0;j++)
{
if(s[i]-s[i-j]>x)
break;
if(s[i-j]-s[i-2*j]<=x)
{
dp[i][0]=min(dp[i][0],dp[i-2*j][1]+1);
dp[i][1]=min(dp[i][1],dp[i-2*j][0]+1);
}
}
}
if(dp[n][(m-1)%2]>m-1)
return 0;
else
return 1;
}
int main()
{
// freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
s[0]=0;
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
s[i]=s[i-1]+x;
}
if(n%2==1||2*(m-1)>n){
printf("BAD\n");
continue;
}
int l=1,r=s[n];
while(l<r)
{
int mid=(l+r)/2;
if(check(mid))
{
r=mid;
}
else
l=mid+1;
}
printf("%d\n",l);
}
return 0;
}