课程总结----第八周(先发后补喽)

4.27 训练收获:
C题:
想到肯定与最大最小值有关,因为团队除了问题,谁都不想去认真做题。慢慢调整。
思路一:对最高的进行修减,最低的不必修建,直到所有花等高。举一组样例,规律其实很好找,不必逆向思维。
思路二:将花修减到等高,必定要对最高的进行处理。逆向思维,也就是将每朵花加1,和最高的相等,如果这个和sum小于最大数,则成立。(最大数-sum)表示最后修减的高度。

D题:主要是取模的问题。2的64次方无法表示,已经越界了,结果显示为0。其他的都已经想明白了。看完题解,发现把问题想简单了。

E题:本题过了,但是代码实现不够精炼。我们采用数组记录连续的字串数目;其实用while当遇到一样的便进行记录,下标累加,另开个变量直接进行记录总和。

4.28 训练收获:
E题: 采用的是string数组,因为一个小错误,wr了四发才过,罚时太多,队伍状态不好,但在回暖。想到用map,但都没信心用这个方法去写,复习一遍。
三种表示用法,重点记住数组表示的即可,了解迭代器用法。

map<int,string>s1;
map<int,string>s2;
 for(int i=0;i<n;i++)           //统计相同个数
    {
        for(int j=0;j<m;j++)
        {
            if(s1[i]==s2[j])
                c1++;
        }
    }
迭代器:
map<char,int>mp;
   mp['m']=20;
   mp['r']=30;
   mp['a']=40;
   for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
   {
       printf("%c %d\n",it->first,it->second);
   }

A题:
好不容易看懂了题意,却没跟队友说明白意思,最后掐着时间点侥幸过的。
题意:给定一个数组,可以补x个数,从1开始,数组中有的不必补充,最大能补到多少,输出这个数.
例子:
20到40,只需要填充19个数,x减去填充数值,填充完后数字要更新为40。

 temp=(a[i]-a[i-1]-1);  //填充数

注意点:
1.会出现一种特殊情况。刚好x消耗完,但是数组中有几个数能跟在后面。
2.去重操作: int t=unique(a+1,a+n+1)-(a+1); 这个技巧很棒,能免去很多讨论。
3.当最后一个数被补充完后,但是x并没有被消耗尽,因此要加上x。

4.29 cf比赛收获:
前两个水题模拟下就过了,收获就是一些细节处理:

int temp=(r+b-1)/b ;    //a题非常好的进一方式

重点讲一下c题和d题
(插一句,多么希望自己能过掉c,d题,两题思路都有点正确,代码的处理也找到了方法,也尽力尝试了下,但还是做不出来。看似距离ac很近,其实差的还是非常多)
C题:(两种方法,第一种只用map)
我的思路:第一时间想到了用map,第一个关键字为学生注册学校,第二个为学生技能值。然后分别统计每所学校学生的技能值,记录i前的总和。根据k的不同值,利用统计的和减掉技能值低的总和。然后累加到输出的数组ans[n]中。
思路缺陷: 标准的map+vector解题
1.只是简单会用map。第二个关键字应该是int类型的vector容器,因为同一所学校记录不同的技能值。

int n;cin>>n;
        vector<long long int>a(n,0),s(n,0);   //定义n个元素,初值都赋为0
        for(int i=0;i<n;i++)
            cin>>a[i];
        for(int i=0;i<n;i++)
            cin>>s[i];
        map<long long int,vector<long long int> >b;
    //b为map容器,第一关键字为学校代号;第二个用vector容器记录此学校不同技能值

2.vector默认从0开始存,迭代器begin也是从0开始记录的。所以如果从1开始存的话,既不便利迭代器的使用,也使得第二关键字的排序不便。

for(it=b.begin();it!=b.end();it++)
        {
            vector<long long int> temp=it->second;
            sort(temp.begin(),temp.end());
         }

3.数据的存入和对于k值的判断(从1开始思考的形式)可以分开看,但要着重注意下标

           long long int sum=temp[temp.size()-1];
            ans[0]+=sum;
            for(int i=2;i<=temp.size();i++)       //从1开始思考的数值判断
            {
                long long int r=temp.size()%i;  
                if(r)
                    ans[i-1]+=sum-temp[r-1];     //存入数据
                else
                    ans[i-1]+=sum;
}

第二种代码方式:
1.也是采用vector容器,是一个二维容器。每一个a[i]都是一个数组存放这着这所大学学生的技能值。思路大同小异。

 for(int i=0; i<n; i++) a[u[i]].push_back(s[i]);

从下表1开始的二维vector容器对于每一个数组的排序。

for(int i=1; i<=n; i++) sort(a[i].begin(),a[i].end());

3.先记录每组的前缀和。再用前缀和 减去 取模值的前缀和。即为学生参赛的技能数。

 for(int j=1; j<=k; j++) sum[j]=sum[j-1]+a[i][j-1];
 for(int j=1; j<=k; j++) sth[j]+=sum[k]-sum[k%j];

D题收获
竟然是一道DP题目,我竟然又没写出来。我还以为要去找数学规律,真的迷。
我的思路:其实刚看题目心中就有两个想法,一个是用DP,这个感觉是对的;但是之前看到过一个类似两个数组比较的题目,还有离散化的从处理方法,不自觉就去找两个数组之前的关系,这个方向就错了。
1.确定DP数组含义。两个数组都从第i个数开始到第j个数交换能获得的最大值。
2.找到状态转移方程。dp[i][j]=dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i]-a[i]*b[i]+a[j]*b[j]
在这里插入图片描述

3.确定初始状态。初始化为0即可。


递归补充:经典 汉诺塔问题(其它忽略,主要理解递归过程)
递归的总过程就是当程序运行到某个阶段调用自身,会暂停当前任务,转而去调用下一层,直至运行完,在执行当前任务。暂停当前任务,转而去做递归函数,完成后在转而继续当前的任务。

H(n)=H(n-1)+1+H(n-1)

先将(n-1)个圆盘放到辅助柱上,再将最大的放到目标柱上,最后把辅助柱上的(n-1)个放到目标住上。(2的n次方-1)

G题递归代码:
一个朋友跟我说,他并不理解递归,但是他会用,就让我很惊奇。想想确实,递归再代码中起到的作用其实并不难理解,难得是理解递归从上至下触底然后逐层返回的过程。
总之,会用然后做出题才是目的。

int he(int x,int y)
{
    if(dp[x][y]>=0)
        return dp[x][y];
    dp[x][y]=0;
    for(int i=0;i<=a[x][y];i++)
    {
        for(int j=0;j<=a[x][y]-i;j++) //不必能量消耗完停
        {
            int x1=x+i;
            int y1=y+j;//控制往右走,往下走
            if(x1<1||x1>n||y1>m||y1<1)
                continue;
            int t=he(x1,y1); //走在这一步时在从这搜索路径累加
            dp[x][y]=(dp[x][y]+t)%10000;
        }
    }
    return dp[x][y];
}

H - Worm
(换了个方法,竟然过了,很棒)
1.第i天虫子到第j棵树的最大方案数。
2.第i天第j棵树的最大方案数为前一天(j-1)和(j+1)的方案数和。
在这里插入图片描述

3.将dp数组清0,因为虫子开始在第p棵树,所以dp[0][p]=1

I - Monkey and Banana
1.到第i个位置时累计的最大高度。
2.错误想法:一重循环,以第一个为标准,往后遍历满足条件的块状。
实际不一定以第一个为标准,只要是第i个之前的都有可能当作基底。所以必须是两重循环:以第i个为标准,向前遍历满足条件的,查找最大值。记录下成为子问题,下次可直接用。

 for(int i=0;i<m;i++)
    {   dp[i]=t[i].z;
        for(int j=0;j<i;j++)
        {
            if(t[j].x>t[i].x&&t[j].y>t[i].y)
            {
                dp[i]=max(dp[i],dp[j]+t[i].z);
            }
             ans=max(ans,dp[i]);
        }
    }

3.初始化清0即可。


开心的发出笑声,一路走下去

吼吼吼,累死累死~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值