牛客–放小球问题
问题描述:n个桶中小球的个数已知,可以操作k次(每次从桶中取出一个球,或者添加一个球),每个桶有规定的最大容量,到最大容量不能放球,桶里没球了也不能拿球.求操作k次后两相邻桶之间的最大差值的平方
输入示例: 5, 4, [1,2,3,4,5], [15,15,15,15,15]
解释:5个桶 操作4次 桶内的小球分别是1,2,3,4,5 桶的最大容量都是15
class Solution
{
public:
int solve(int n,int k,vector<int> &a,vector<int> &w)
{
int l=0,r=500;
int ans;
int f[105][505];
while(l<=r)
{
int mid=(l+r)>>1;//假设最后的差值是mid ,用动态规划来计算差值是mid的时候最小的移动步数,如果小于等于k就是可行的然后继续搜寻较小差值
memset(f,0x3f,sizeof(f));
for(int i=0;i<=w[0];i++)
f[0][i]=abs(a[0]-i);//初始,0号索引位各个 球数和本来球数的距离
for(int i=0;i<n-1;i++)//计算每一个箱子和后面一个箱子在满足小于等于mid差值时,各个状态所需要的最小变动球数
{
for(int j=0;j<=w[i];j++)//从i号箱子中有j球个数开始
{
int mn=max(0,j-mid);
int mx=min(j+mid,w[i+1]);
for(int z=mn;z<=mx;z++)//i+1号箱子里有z个球时需要移动的最小距离.
f[i+1][z]=min(f[i+1][z],f[i][j]+abs(a[i+1]-z));
}
}
int now=f[n-1][0];//
for(int i=1;i<=w[n-1];i++)
now=min(now,f[n-1][i]);
if(now<=k)
{
ans=mid;//mid其实就是最后寻找的那个最大差值;
r=mid-1;
}
else l=mid+1;
}
return ans*ans;
}
};