程序员

课程总结 第六周

作者:admin 2021-07-19 我要评论

收获 尼姆博奕 看了好多博客开始还是比较容易理解深层面的较难看懂尤其是尼姆博奕的变型还有后面涉及SG打表那一块。总结一下自己的认识,简单的跳过。 先看奇异局...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

收获:
尼姆博奕:看了好多博客,开始还是比较容易理解,深层面的较难看懂,尤其是尼姆博奕的变型,还有后面涉及SG打表那一块。总结一下自己的认识,简单的跳过。
先看奇异局势,(s[1],s[2],s[3]…… s[n]),逐步进行异或运算。
若结果为0:那么先手必败;若不为0,那么先手必胜。(也就是说面对奇异局势的人必输)

阶梯博弈算法(尼姆博弈进阶):啃了两三天,头都晕了,证明过程也看的迷迷糊糊。
题目形式:一个楼梯上每层都放有一些石子(硬币也可),每回合将i台阶上石子移动到(i-1)阶上,最后无法移动的输,也就是其他阶都为空,移动第一阶得人赢。
公式:所有的奇数阶上的石子进行异或运算>0,则确定是胜方。因为对于败方来说,若移动奇数阶的石子,胜方便有可将奇数阶石子异或为0,成为奇异局势;若移动偶数阶石子,胜方可将败方移动的石子往前移动,对奇数阶石子无影响。

到这里还好,可根据阶梯博弈变化的题目真的很难,看都看不明白。会继续认真看的。
举一个阶梯博弈变化的题目。一个盒子从1到n被标记,满足:
(A>B&&(A+B)%2==1&&(A+B)%3==0),不能移动盒子的人输。

我的思路:想到了阶梯博弈,可还是不会用,发现条件可转化为(A+B)%6==3,然后举例了1到15数字的移动情况,不难发现最终都会移动到(1,3,4)这个盒子中。经查阅资料:发现要对所有奇数步盒子的礼品数进行异或运算,而所有满足奇数步盒子都满足*(A+B)%6==0或2或5*,这一步简直太难想了!!

威佐夫博弈:核心公式:(1.0+sqrt(5.0))/2*(a-b) 大体是两堆石头,要么从一堆中取任意数,要么从两堆中取相同数目,先去玩的获胜。这里的奇异局势和尼姆博弈的很像,但没有尼姆博弈难,毕竟尼姆博弈是从n堆石头中取。
需要注意的点:
1.从一堆中取可能可以得到奇异局势。2.从两堆中取一样的石头也可能得到奇异局势。要根据题目要求灵活改变。

k倍动态减法:这个同样非常难,看了好久都还是很懵,也能看做是斐波那契博弈的变型,只是不再是两倍了。当k=1时,2的i次方都是必败点,将n化为用二进制,每次拿走最后的一个1,而对手不能拿走倒数第二个1,因为他拿的数量不能多于你拿的;当k=2时,斐波那契数列都是必败点;当k>=3时,开两个数组a[n],b[n],a[n]存的数字都是必败点,b[t]是a[1到t]所能表示的最大数,最后要使得

b[i]=b[t]+a[i] (a[t]*k<a[i]

具体实现代码:(还没完全理解),目前还是先记住再说,适用性广

while(n>a[i])
        {
            i++;
            a[i]=b[i-1]+1;
            while(a[j+1]*k<a[i])
                j++;
            if(k*a[j]<a[i])
                b[i]=b[j]+a[i];
            else
                b[i]=a[i];
        }

记忆化搜索:看了很多资料,感觉还是难在理解递归式状态转移方程那里。
1.概念其实很好理解,搜索过程中,避免重复计算,记录一些状态的答案,在接下来状态中可以直接使用。2.记忆化搜索只是类似于动态规划,不是属于。具体是倒着的递推式动态规划。

题G:

Y题收获:题意省略
1.开一个二维数组,如果要对其中某一行进行初始化memset(dp[1],0,sizeof(dp[1]));这个代码是可以实现的,但要注意:只能初始化为0,若初始化为1或其他数,会出现乱码。
2.然后就是我的思路:首先确定要定义一个二维数组dp[i][j],想到用i来控制最大值为多少的方案数案数,j来表示具体取得末尾的数字。记录的是方案数,当i等于k时,表示最大数字为k,再从1到n遍历所有方案数累加
大致思路没问题,有些细节没想到:1.如何控制取得的数,由于题目中后一个数字要整除前一个数字,于是又要加一重循环来控制乘的跨度(1,2,3…)。问题看似处在代码实现上,其实还是思路没想好。
3.就是取模要及时,每次累加都要。一个注意点。

F题收获:给定一个字母矩阵,规定可替换的字母,要求所有字母一样的最大子矩阵的面积。(花了一个上午,弄得我心累的一题)
首先是题意:和我理解的有偏差,我并没从题目看出求面积的意思,我认为只要求出最大子矩阵相同字母的个数即可。----->>>方向上就错了,虽然自己也不太会做。
我的思路:虽然自己没思路,但也想了好久。我发现,替换的情况有很多,肯定是分类讨论。也想到了将字母全变成a或b或c,全变成a去找最大子矩阵(b,c同理),到这里是对的。然后我想直接去找字母见得关系,比如最大子矩阵a,如果左边或上边是a累加1,其实行不通,这只是在记录a的次数而已。
查了题解后,题解都看了好久才懂,很多困扰的难点都有了解释。
1.为了方便记录,用数字代替字母,出现a则标记为1;然后先只考虑纵向上a出现的次数,若a上方也是a,累加1。

2.更妙的是他计算面积的方式。因为在步骤1中考虑了纵向,接下来考虑横向就好。dp[i][j]是第i行第j个字母,所表示的值便是这个子矩阵的高,以它为中心,然后向右取比它大的,向左取比它大的,得到最大宽,计算面积取最大。是之前没见过的查找方式!!!(关键是另外开两个数组)

 for(int j=1;j<=n;j++)
       {
           while(dp[i][j]<=dp[i][l[j]-1])
            l[j]=l[l[j]-1];
       }
       for(int j=n;j>=1;j--)
       {
           while(dp[i][j]<=dp[i][r[j]+1])
            r[j]=r[r[j]+1];
       }

L - Sonya and Problem Wihtout a Legend 收获:
本题用了离散化和一些数学知识,看完资料后,才懂了一点,慢慢用到了高数知识和结论了。题意:要求用最少的步数构造一个严格的上升数组。
数学结论:如果是上升数组,肯定满足 (a[j]-a[i])>=(j-i),所以便得到 (a[j]-j)>=(a[i]-i),所以用数组b[n]存储(a[i]-i)的值,并进行排序。abs(a[i]-b[j])为正在处理第i位时以b[j]为基准最小花费步数,而dp[i][j]为处理到第i位时以b[j]为基准总体上最小花费步数,是需要加上 上一步同样以b[j]为基准总体上最小花费步数,和同样处理到第i位时以b[j-1]为基准最小花费进行比较取最小。
构造状态转移方程:dp[i][j]=min(dp[i][j-1],dp[i-1][j]+abs(b[j]-a[i]));

4.14训练赛:
1.我负责的那道题没有过,因为忽略了一种情况,一直卡住,所以比别人少做一道题,很自责,加油吧!!!
思路:大致都是对的。两端的树就往两边倒,中间的树减去相应距离或加上相应距离不和两端的树相交,然后累加。之所以没过:非要用ans去记录才差值想着方便一点,结果把自己搞晕了,因为ans的值需要不断更新。
2.D题我的思路是找规律,规律已经快出来了,但还需要时间。队友直接模拟,我觉得也很好。卡住我们的难点:要过菜品个数进行排序(保证剩余的的菜品先进行配对,这样才能保证最多,参考样例:2 3 2)。
3.A题我们思路是完全正确的,但是代码实现上有问题,就被搁置了,没想到别人都过了,特别亏。其实代码实现也很简单,一个数找0和8,2个数两重循环枚举遍历,三位数类似。
教训:
1.有些问题是自己想得复杂,不是题目复杂,可能和心态有关,心态要放平。
2.如果确定思路正确,就不要轻易的放弃代码实现,代码是可以慢慢调的。
3.我负责那题就是我把问题复杂化,定义了一个ans记录位置

4.15训练赛:
1.一个代码实现出现了问题,整个队浪费了将近40多分钟。忽略了一个问题,如果这个‘1’是在最后出现的,那么没有一个‘0’去累加这组1的长度。难受了!

**4.16训练赛:**主要两个差距,前半段一直是领先的,后面心态问题特别着急,导致一个简单题目没做出来:另一个是H题,没写出来,和其他组的差距,要努力追赶并超越!!!
H题:
两方面原因:1.看题不仔细,看的有点快,没发现输入一栏中的条件
1<=b[i]<=2n。2.还有就是代码实现,没法将思路很好的转化。收获到一个没想到的代码实现形式。

for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            m[a[i]]=1;    //将出现的元素标记!!
        }
        int temp;
        for(int i=1;i<=n;i++)
        {
            b[i*2-1]=a[i];      //若一个数组是另外一个数组的两倍,可根据特征记录)
            temp=a[i];
            while(m[temp]==1)
            {
                temp++;
            }
     (后面代码就很平常,省略)

技巧,注意点
1.除要用double。
2.异或运算
1.异或的一个运算规律: A^B=C --->>> C^B=A;
2.‘^’ 的优先级小于 '> , <',注意加 '( )'

赛后补题:(不放代码,主要是思路,错误的点和收获)
一.C. Divisibility by Eight
思路:是完全正确的。能被8整除的数:1000+b;只要保证b能被8整除即可。分别遍历1位数,2位数,3位数.(采用循环方式,暴力做即可)
错误的点:个位如果取了这个数字,十位数是从这个数字前开始取,百位也是从十位取得数之前取。
收获:(整理一下数字特征)
能被2整除的数:奇,偶取模于2即可。
能被3整除的数:各个位上数之和能被三整除。
能被4整除:最末两位数字能被4整除即可。
能被5整除:末位为0或5.
能被6整除:同时能被2和3整除的条件。即是偶数,且各个位数之和能被3整除。“12”同理。
能被7整除:abc def ghi jkl,满足(jkl-ghi+def-abc)能被7整除。“13”同理。
能被8整除:最后三位数字能被8整除。
能被9整除:各个数字之和能被能被9整除。
能被10整除:末位为0。
可被11整除:(奇位数字和-偶位数字和)能被11整除。

二:B. Balanced Array(水题跳过,过了一遍代码,当时敲的时候思路不清,整理一下)

三…A. Candies(水题,唯一要注意的点)
收获:pow()函数的计算方式存在误差
---->>>处理方式:加上一条常变量const int eps=1e-6; (放主函数外面)。不然就用double

四:C. Alternating Subsequence
我的思路:
1.首先要保证取得子段最长。将观察发现,如果第一个元素是正,那么最长的便是“+-+-+-+-”这种形式;如果第一个元素是负,那么最长的便是“-+-+-+-+-+”这种。
2.之后两种实现方式,第二种更巧妙一些。都是找同符号下最大的元素累加。
关键实现方式:如果找到了正号下最大的元素,那么是在负号语句中加;同理,负号最大的元素在正号语句中加。不然无法实现加和最大,卡了好久。还有最后的和并未加上最后一个找到的同符号最大值。
第二种实现形式:用乘积来判断正负号,如果和前一项同号,乘积为正,然后找最大值;之后再乘积为负的时候加上去。

五.Tetrahedron
做了那么多的dp题目,发现自己根本就不会dp!!!学的好乱,一定要花时间整理。即使本题是一个很水的dp,我都做不出来。有很多零星的想法,代码写不出来,真的会很失落。简要讲一下思路:
首先:确定dp[i][j]表示的含义,第i步时到达某点的最大方案数。
其次:找dp转移方程。因为一个点有三种方式到达,所以要再加一重for循环。

dp[i][j]+=dp[i-1][g]  (g表示从除自己所处点之外某个点,表示上一步g点的最大方案数)

虽然每次训练赛因为各种原因都输的很不甘心,但只有不断的完善,找到队伍的问题,总结自身的原因,不断鞭策自己,不断追赶别人,也还不错。但说到底,没有人愿意输,相信一定会追上并超越,不用怕爬的慢,不为给他们看!!!

;原文链接:https://blog.csdn.net/weixin_51934288/article/details/115642063

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 数智洞察丨和死神赛跑,那些不得不“闯

    数智洞察丨和死神赛跑,那些不得不“闯

  • 酒店小程序开发瑞蚁解决方案

    酒店小程序开发瑞蚁解决方案

  • 自建Kubernetes集群如何使用阿里云CSI

    自建Kubernetes集群如何使用阿里云CSI

  • 【kafka运维】数据迁移、分区副本重分

    【kafka运维】数据迁移、分区副本重分

腾讯云代理商
海外云服务器