难度中等290
有一堆石头,用整数数组 stones
表示。其中 stones[i]
表示第 i
块石头的重量。
每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x
和 y
,且 x <= y
。那么粉碎的可能结果如下:
- 如果
x == y
,那么两块石头都会被完全粉碎; - 如果
x != y
,那么重量为x
的石头将会完全粉碎,而重量为y
的石头新重量为y-x
。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0
。
思路: 若石头可以对应粉碎,则可以将石头分为两部分 。
其中 X,Y表示各部分的重量,M为石头的总重量,则 X+Y = M;
min(X,Y)<= M/2、max(X,Y) >= M/2 ;
实际粉碎的重量为 2*min(X,Y);
则最终剩余的部分为 ans = M - 2*min(X,Y) = |X-Y| >= 0 ;
获取最小的 ans ,为 X 和 Y 的差值最小,即 min(X,Y)尽量大,或者 max(X,Y)尽量小。
①将最小剩余重量寻找问题,转换为 小于 M/2 的最大可能重量,或者大于 M/2 的最小可能重量。
②不大于某值的最大可能重量(背包问题-DP)
代码:
int lastStoneWeightII(vector<int>& stones) {
int sum=0;
for(auto index:stones) sum+=index;
int len=sum/2;
bool data[len+1];
memset(data,false,sizeof(data));
data[0]=true;
for(int index:stones){
for(int j=len;j>=index;--j){
data[j] = data[j] || data[j-index];
}
}
for(int i=len;;--i){
if(data[i]) return sum - 2*i;
}
return sum;
}