四校联合第一次周赛G、H题解

G盲僧与计算几何

题意:给定五个点,求一条直线上最多有几个点

思路:每三个点abc,可以组成两个向量ab和bc,如果两向量平行则两向量在一条直线上(因为有公共点b),向量平行可以用x1*y2=x2*y1判断.如果abc在一条直线上,abd在一条直线上,则abcd都在一条直线上,所以,先枚举前两个点,然后枚举其它点,就可以求出最多有几个点在一条直线上。当然,也可以用斜率算,但有可能会被卡精度,推荐使用乘法。

核心代码:

        for(i=1;i<=5;i++){
            for(j=i+1;j<=5;j++){
                int cnt=2;
                for(k=1;k<=5;k++){
                    if(k!=i && k!=j){
                        int x1,x2,y1,y2;
                        x1=a[j].x-a[i].x;
                        y1=a[j].y-a[i].y;
                        x2=a[k].x-a[j].x;
                        y2=a[k].y-a[j].y;
                        if(x1*y2==x2*y1)
                            cnt++;
                    }
                }
                ma=max(ma,cnt);
            }
        }




H魔刹石与数据芯片

题意:n分钟,两个工地,两种材料,每分钟可以换工地,或在当前工地工作,或出售背包中的材料,求最大收益

思路:由于对于每分钟可以进行多种不同操作,无后效性,所以可以用动态规划来做。带有一点贪心的思想,同时卖两种材料一定不是最优解,因为每分钟得到的材料数固定,收益只与卖的时候的价格有关,在第i分钟,如果卖第一种材料收益更高(time*x*val1>time*y*val2),那么就让它在上一次买材料后全部时间来搬第一种材料,抽时间搬第二种材料收益一定更低,所以收益最大化一定是在当前工地卖当前材料。          

如果在第i分钟卖第一种材料可以使收益最大化,那么前一个状态就是在第j分钟(j<i)卖完某种材料后到第一个工地一直搬到第i分钟然后出售

用dp[n][m]表示第n分钟时进行m操作的总收益,另0代表在工地1搬砖,1代表在工地2搬砖,2代表卖材料1,3代表卖材料2。则:

                dp[i][2]=max(dp[i][2],dp[j][2]+(i-j-1)*val1[i]*x);
                dp[i][2]=max(dp[i][2],dp[j][1]+(i-j-1)*val1[i]*x);
                dp[i][2]=max(dp[i][2],dp[j][0]+(i-j)*val1[i]*x);
                dp[i][2]=max(dp[i][2],dp[j][3]+(i-j-2)*val1[i]*x);
                dp[i+1][0]=dp[i][2];
                dp[i][3]=max(dp[i][3],dp[j][0]+(i-j-1)*val2[i]*y);
                dp[i][3]=max(dp[i][3],dp[j][3]+(i-j-1)*val2[i]*y);
                dp[i][3]=max(dp[i][3],dp[j][2]+(i-j-2)*val2[i]*y);
                dp[i][3]=max(dp[i][3],dp[j][1]+(i-j)*val2[i]*y);
                dp[i+1][1]=dp[i][3];

这样写有一些多余的状态,有些状态转移一定不会是最优,但思路清晰,理解后可以自行尝试去掉冗余的状态转移。

因为初始在工地1,所以dp[1][2]和dp[1][3]是不存在的,需要特判.

两层循环(i,1-n),(j,1-i) 时间复杂度O(n2),空间复杂度O(n)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值