2021年3月22日-3月28日ACM学习日志

本周学习:贪心的题,codeforces上的比赛和初学动态规划

一:贪心的题也做了两周了,思想很易懂,但题千变万化。我觉得还是做的太少,看见一个题不知道往哪想才对。

总结下这周做的题,

1.最优问题,比如给你每天生产一单位牛奶的成本(每天成本不同),和放仓库一周的价钱 ,按照客户每周的需求量,怎么才能成本最少。
想法思路:我一开始看题看错了,以为放仓库一周的价钱就那些呢,后来才看见是那是一单位放一周的价钱,当时就想如果这周的成本比下一周少,那么我们就在这周把下一周的牛奶也生产出来,写下代码不对,又重新审题,发现自己理解错题了,然后用这周的成本加上放仓库一周的价钱和下一周的成本作比较,最后就AC了。
本题总结:先读通题意再去写代码,我以前是一边写代码一边想思路和理解题意,这样真的好傻,从周四晚上的比赛上我就看出来了,我一定要先理解好题意,在脑子里想好思路再去写代码,我以前就觉得一刻不写代码就慢一步,我应该持有“磨刀不误砍柴工"的思想
2: 还有一个最小值问题,真的好让我头大。给出一组A[N].求V = (|A(1) – B(1)| + |A(2) – B(2)| + … + |A(N) – B(N)|) + (|B(1) – B(2)| + |B(2) – B(3)| + … +|B(N-1) – B(N)|)的最小值。看着题目字数很少,我以为很简单呢,没想到却困扰了很久。
想法思路:我把N确定为3,然后想着把A数组排排序,然后想着每个都有绝对值嘛,对于每个A我的B只要和A差值一样就行,就想着我使每个B[I]都比A[i]大,我想去掉绝对值,然后算了算数学式子,结果得出B2+2*B3-A1-A2-A3,然后我就以为和B1无关呢,真的,我真的是乱想了,一点解题的思路方法都没有,就想到什么就怎么弄,没有一个固定的思路模式,过了一天,,把数据放在一个数轴上,我又发现每个b[i]要和a[i],b[i-1],b[i+1]的距离最短即可

int minn(int a,int b,int c)
{
    if((a>=b||c>=b)&&(b>=c||b>=a))
        return b;
    else if((c>=a||b>=a)&&(a>=c||a>=b))
        return a;
    else
        return c;
}

总结:做题太少,看到题不能有很好的想法,总是在试错,还有一点就是过于自信,看着题简单,其实只是自己没有真正读懂题意,还有就是自己有一点思路,但这个逻辑还没真正弄明白,就有一点思路,一些边界问题都没有搞懂就开始写代码,必错。还是要真弄明白再去写代码,不然稀里糊涂的写完代码自己都不懂。
3:加工木棍问题,一个木棍有长度l和重量w,如果下一根木棍的l和w都大于这根木棍,那机器则不用改变,否则,要加上1 分钟的设置时间。求加工这些木棍的最短时间。
想法思路:我看题中给出的测试数据,认为遍历一遍,再定义个cmp函数从小到大排序就可以了,写着写着我就发现,排序完,那么后面多余的木棍可能还能有一个排序,所以我用一个b数组存储第一次排序中剩余的数据,然后我用这个数组再排了一下序,刚排完就发现,下面剩余数据可能还有一个排序,所以我这种方法是不对的,然后我就想到了老师说的vis数组,如果已排序则是true,没排序则是false。然后就AC了。
总结:在这期间,我提交了三次才AC,究其原因,是因为cmp函数用代码的写思路的呈现能力不足,自己的想法无法用代码写出来。
错误cmp函数:

bool cmp(const node a,const node b)
{
    if(a.l<b.l)
    return true;
    return a.w<b.w;
}

正确cmp函数:

bool cmp(const node a,const node b)
{
    if(a.l==b.l)
    return a.w<b.w;
    return a.l<b.l;
}

4:小岛问题(区间重叠)(反向思维)
海岸线的上方是有小岛,海岸线上有雷达,给出各个小岛的坐标,能够把所有岛检测到而且需要最少数量的雷达(检测范围s),求这个最小数量。
想法思路:这个题是vj作业上的c题,但我一直没做,之前看了很久,一直没思路,这怎么弄,我一直在思考,我的雷达应该放在哪才能检测更多的小岛呢,有段时间,我还想求雷达的具体坐标。后来实在不会就看了题解,这就用到了反向思维,我不一直盯着雷达的检测范围,我盯着小岛,我用x-sqrt(ss-yy)和x+sqrt(ss-yy),算出两个值,算是一个区间,如果区间有重叠,那么一个雷达必然能检测到。
总结:要有反向思维,如果正着想没有思路时,不妨用别处想一想,另外,我现在觉得代码不是最重要的,最重要的是我的想法,思维。现在还是懂得太少,不能看见题就知道往哪想,还是要多做题训练思维才是。
5:两个优先级的贪心
有n个命令,要通过p个,某主席要在通过的p个中选择k个接受。 每个命令有两个值ai,bi, ai表示如果该主席接受该命令,他的头发变灰的数量,bi表示如果该主席不接受该命令时,议员不高兴值。 对于通过的p个命令,该主席要使议员的不高兴值和最小,在相同的情况下,要使自己的头发变灰的数量尽可能的少。 让你求出通过哪p个命令,使得该主席的头发变灰的数量最多,在相同的情况下,输出使议员不高兴最大的选择。
想法思路:这个题是老师上课讲的,如果我自己做,我还真不会,但这个题看一看还是挺有意思的,以前没有遇到过这种要两个贪心的题。我们先从主席的角度选,主席肯定是无论掉头发多少,也要让议员不那么生气,如果不高兴值相同,那就选掉头发少的。所以我们写一个cmp1函数,就按b从大到小,a从小到大排序,前p-k个我们不选。然后我们从议员的角度想,议员想让主席掉头发最多,而且我们选的还要让主席选上,所以我们选的命令在掉头发相同的情况下我们还要让不高兴值比较大。我们再写一个cmp2函数,按a从大到i小,b从大到小排序,取前p个,这p个就是我们让主席选的然后剩余p-k个,我们要选出那种主席在比较之下,不得不选我们选的那p个命令。我们就选那种比我们选的那些命令不高兴值小一点的。

bool cmp1(struct Inf a,struct Inf b)
{
   if(a.bi!=b.bi)
      return a.bi>b.bi;
   return a.ai<b.ai;    //从主席这一方面考虑,在相同的愤怒值中,他会选a小的那个命令


bool cmp2(struct Inf a,struct Inf b)
{
   if(a.ai!=b.ai)
      return a.ai>b.ai;
   return a.bi>b.bi;   //尽量把愤怒值小的往后放


#include <bits/stdc++.h>
using namespace std;
#define N 101000
 
int n,k,p;
 
struct Inf
{
   int ai,bi,ii,bbii;
}inf1[N],inf2[N];
 
bool cmp2(struct Inf a,struct Inf b)
{
   if(a.ai!=b.ai)
      return a.ai>b.ai;
   return a.bi>b.bi;  
}
 
bool cmp1(struct Inf a,struct Inf b)
{
   if(a.bi!=b.bi)
      return a.bi>b.bi;
   return a.ai<b.ai;  
}  
int main()
{
   while(scanf("%d%d%d",&n,&p,&k)!=EOF)
   {
      for(int i=1;i<=n;i++)
      {
         scanf("%d%d",&inf1[i].ai,&inf1[i].bi);
         inf1[i].ii=i;
      }
      sort(inf1+1,inf1+n+1,cmp1);
      memcpy(inf2,inf1,sizeof(inf1));
      for(int i=1;i<=n;i++)
         inf1[i].bbii=i;
      sort(inf1+1,inf1+n-(p-k)+1,cmp2);
      int j=0;
      for(int i=1;i<=k;i++)
      {
         printf("%d ",inf1[i].ii); 
         j=max(j,inf1[i].bbii);
      }
      sort(inf2+j+1,inf2+n+1,cmp1);
      for(int i=j+1;i<=j+(p-k);i++)
         printf("%d ",inf2[i].ii);
      putchar('\n');
   }
   return 0;
 }

本题总结:两个优先级,第一次遇到,第一次知道了还能这样排序,一个排序,有两部分,以前真没想到还能这样。这样的题也过于复杂,所以我们可以先去掉一些条件然后去思考,然后再加上一些条件,一部一部来,搞清一部再去加上一些条件。

一些代码小细节:

判断奇偶:

if(n%2==1)//奇数
if(n%2==0//偶数
//运用位运算
if(!n&1)//奇数
if(n&1//偶数

本周学习感受

:上面在题中的总结中也有部分感受,我就不一一例举了,说点别的,首先,这一周的贪心比上一周难的多,也第一次打了一次比赛,虽然假期里也打过,但当时不是太认真,想当然,我也没有a过题,这周四打了一场,ac了一道,和以前做题真的有点不一样,第一,做题有时间限制,第二,比起做贪心作业,因为没有题解,自己做起来也比较慌,第三,做不出来就没分啦。综合起来,自己就是慌,甚至有点害怕,害怕自己做不出来一道题。这也就是比赛的真实感受了,也是锻炼我的抗压能力。然后就是老师讲的课,可以看出,题越来越难,我个人认为真的好难,我上课都是懂个大概,下课也要看上很久才能搞明白。但有时候题真的挺有意思,还有就是自己弄懂后,就感觉对自己有点欣慰,这种感觉不错。还有就是vj上的贪心的题,经过两周的学习,我在面对一些题时,也有了思路,但还是不熟,一天能AC上2道,我就感觉不错啦,真的,贪心思想很简单,但题确实千遍万化,就感觉每一道都不是太好做,都要想很久才行,有了思路,我的代码也是错误百出,还要调试很久才行,好不容易调式好了,一运行还不对,原因有以下几点,1一遍想思路一边写代码,效率慢.2不注意特殊情况和边界问题。3做的少,写的代码也少,自己要调试很久 。4对stl和一些函数不熟悉,只是知道,也想不起来用。嗯,这周还初学了动态规划,也是很难,也没做过动态规划的题,下周总结动态规划。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值