【笔试记录】2020.8.21 阿里-java后台开发(过河问题、下棋完美度问题)

牛客大佬的全ac代码

链接

过河问题

在这里插入图片描述
当人数超过4人时,每次过河都有两种方案,择优选取。
1、最小送最大的先去,最小的回来;然后最小的陪倒数第二大的去,最小的再回来。
2、两个小的一起去,回来一个小的;然后两个最大的一起去,回来另一个小的。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#include <vector>
#include <iomanip>
#include "limits.h"
#include "math.h"
using namespace std;

int main(int argc, const char * argv[]) {

    int t,n;
    cin >> t; //测试数
    while( t-- ){
        cin >> n; //人数
        vector<int> weights(n);
        int w;
        //输入体重,即时间
        for(int i=0; i<n; i++){
            cin >> w;
            weights[i] = w;
        }
        //按体重从小到大排序
        sort(weights.begin(), weights.end());
        //开始计算
        int sum = 0;
        /*
        当人数超过4人时,每次过河都有两种方案。
        1、最小和最大的先去,最小的回来;然后陪一个大的去,再回来。
        2、两个小的先去,回来一个小的;然后两个大的一起去,回来另一个小的。
        */
        while( n>=4 ){
            int plan1 = 2 * weights[0] + weights[n-1] + weights[n-2] ; //第一种方案
            int plan2 = weights[0] + 2 * weights[1] + weights[n-1]; //第二种
            if( plan1 <= plan2 ){
                sum += plan1;
            }else{
                sum += plan2;
            }
            //两种方案最终都是把两个最大的送过去了
            n -= 2;
        }
        if( n==3 ){
            sum += weights[0] + weights[1] + weights[2];
        }else if ( n==2 ){
            sum += weights[1];
        }else if(n==1){
            sum += weights[0];
        }
        cout << sum << endl;
    }
    return 0;
}

下棋完美度问题

在这里插入图片描述
假设A选点,B先走,A再走,B掌握主动权,B会赢:

  • B的策略:快节奏,所以在度(无向图的度)最小的邻点中,选择值(完美度)更大的结点
  • A的策略:慢节奏,所以在度(无向图的度)最大的邻点中,选择值(完美度)更大的结点

具体分析:

  • 由于是无向完全图,所以一开始各结点的度都相似,所以A选点在值(完美度)更大的结点,B的第一步肯定是走向值(完美度)第二大的结点。
  • 接下来的每一步我们需要注意,不管是A还是B,在同度的结点情况下,值(完美度)更大的结点都会成为最优目标,所以值(完美度)最大的结点会是度值减的最快的结点,会成为B的最优目标。接下来B的每一步会想尽办法回到这个点,以尽快结束战局。并且当值(完美度)最大的结点回不去的时候,值第二大的点会成为第二大目标。
  • 而A的每一步,每当B回到度最小的点,也就是值(完美度)最大的结点,他都会想办法拉开,去拜访每个还没被访问过的点,以拖延时间。
  • 那么通过模拟我们可以知道,最终场景应该是,B再一次回到值(完美度)最大的结点,此时度已经减为0,A已经无路可走了,战局结束。

计算:

  • 假设结点的完美度存储在数组nums[n]中,并且按照完美度从小到大排列好了
  • 这个推导过程中,n到[0…n-1]的边肯定都会遍历完,所以nums[n-1] * (nums[0]+…+nums[n-2]) 。
  • 且A每次从n往外拉,B又想回,结果发现回不来,就会去n-1,由此n-1到[0…n-2]的边也会都遍历完,即nums[n-2]*(nums[0]+…+nums[n-3])。
  • 两者相加就是最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值