一.例题分析
1、问n个冰淇凌球,k个球能组成一个冰淇凌,在同一个冰淇凌中,要求前一个球质量*2<当前球的质量问怎么使冰淇凌个数最多。最直观上看,n/k如果能都满足条件,那应该就是最多的了,即二分上限,所以,用二分查找,每次把假定的二分中值带入判断。判断冰淇凌球时,用下标j标记第二层的位置,用b[j]复制球的质量,如果满足条件的球数没越界,且当达到k层时即返回。
这题选择冰淇凌球的规则不容易想,限制条件有,上一个球的2倍要小于等于下一个,选择的冰淇凌球数要能达到k层,在这基础上实现总个数最多。尤其要注意球的个数有限,不能越界。(还得再看看判断选不选这部分的代码实现)
bool check(int x)
{
if(!x) return true;
int j=x+1;
rep(i,1,x+1)
{
b[i]=a[i];
}
int i;
for(i=x+1;i<=n;)
{
while(a[i]<b[j-x]*2&&i<=n) i++;
if(i>n) break;
b[j++]=a[i];
if((j-1)/x>=k) return true;
i++;
}
if((j-1)/x>=k) return true;
else return false;
}
2、【bzoj1034】【zjoi2008】【泡泡堂】【贪心】
类似田忌赛马,策略就是从实力最弱的开始出场,能使得浙江队得分最高。计算得分的注意点:按照保证第一个队伍能获得的最高分的标准,即若最弱的能胜,那就从左边继续比较次弱的,左指针右移,否则从最右边开始比较最强的,同时右指针向左移动,再不然相等得一分,其他情况就是用第一个队伍余下最弱的去刚对手余下最强的,保证总体分数更高有,即第一个队伍左指针右移,第二格队伍右指针左移。
3、DZY Loves Partition n个数拆分k个最大乘积
从数学也能知道当拆分的k个数相等时,总乘积最大,所以从平均值左右找起,取附近k个数的乘积。第一个for循环是平均值左侧可取的数乘积,第二个for循环是右侧可取数的乘积。(没大看明白这里more、minv为什么这么计算,但是能感觉到是找与平均数差值的)
LL solve()
{
LL minv = (1 + k)*k / 2;
if (minv > n)return -1;
LL more = (n - minv) / k;
LL rst = (n - minv) % k;
LL ret = 1;
LL x = k - rst;
for (LL i = 1; i <= x; ++i)
{
ret = ret*(i + more) % Z;
}
for (LL i = x + 1; i <= k; ++i)
{
ret = ret*(i + more + 1) % Z;
}
return ret;
}
4、【模拟 贪心】Easy Arithmetic
【题意】初始给你一个正确的表达式,在这个表达式中——1,运算符只有'+'和'-',2,没有前导零,3,没有连续的运算符 4,最后一个字符必须为数字类型,让你在这个表达式中任意添加'+'和'-',不改变其正确性,并且使得操作之后的表达式的直接尽可能大。
对于加法,我们不改变就好;
对于减法,首位配合减法,之后找到第一个(如果存在)不为'0'的digit,中间的'0'都加起来,后面全部加起来。
i==0时并不一定是加法,然而减法是一定有'-'的。
所以我们先判定是否为'-',是的话是做减法处理。
否则的话一定是'+',就按照加法处理。
有一个细节要注意,就是目标串的长度可能达到2n,也就是数组要开到2000+
5、LeetCode 1775 Equal Sum Arrays With Minimum Number of Operations (贪心 排序 推荐)
题目链接:https://leetcode.com/problems/equal-sum-arrays-with-minimum-number-of-operations/
题目大意:给两个值在[1,6]的数组,每次可以将两数组中任意一个数字变成[1,6]中的任何数,问最少变换几次可以使两个数组和相等
题目分析:显然当某个数组可能的最小值大于另一数组可能的最大值时无解,有解情况下的最优操作显然是取能将diff变的更小的操作,要么用和大的数组的大数字减小,要么用和小的数组的小数字增大,两个指针扫一下即可,这种做法需要排序
二、
这周看的贪心不多,但是这是最感兴趣的一个算法,感觉主函数差不多都可以想到,但是贪心标准还有实现部分的函数代码,在细节上会漏掉些条件,甚至有能想到实现的大概,但是不会具体写。这周更多的精力还是放在线代上了,接下来的一周再补一补贪心的部分题,结合课件在开始DP,加油!