题解 | #旅行Ⅱ#

旅行Ⅱ

http://www.nowcoder.com/practice/61d1f87753f04f4fbe4d3cee749ca895

算法思想一:递归+记忆化递归

解题思路:

可以对种状态利用二进制掩码形式逐一对其递归进行搜索,每次查看经费和前后续关系。搜索函数中为当前的状态数,为当前最大这段序列可访问的最大城市数,递归的时候减小经费,改变即可进入子问题。为了防止递归处理的问题太大,可以用数组dp记录所有的前面计算过的序列的可访问的最大值。

图解

代码展示:

C++版本

/**
 * struct Point {
 *    int x;
 *    int y;
 *    Point(int xx, int yy) : x(xx), y(yy) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param N int整型 N
     * @param V int整型 V
     * @param A int整型vector A
     * @param List Point类vector List
     * @return int整型
     */
    int search(vector<vector<int> >& city, vector<int>& dp, vector<int>& A, int N, int V, int m, int n){
        if(dp[m] != 0)
            return dp[m];
        int maxn = n;
        for(int i = 0; i < N; i++){
            if(((1  0 || A[i] > V)  // 如果当前 节点已经走过或者费用不足,就不需要进行搜索
                continue;
            bool flag = true;
            for(int j = 0; j < city[i].size(); j++){ //查看它的前驱节点是否走过
                if(((1 << city[i][j]) & m) == 0){
                    flag = false;
                    break;
                }
            }
            if(flag) //找到最大值
                maxn = max(maxn, search(city, dp, A, N, V-A[i], m ^ (1 << i), n + 1));
        }
        dp[m] = maxn;  //记忆避免多次递归
        return dp[m];
    }
    int Travel(int N, int V, vector<int>& A, vector<Point>& List) {
        // write code here
        vector dp(1 << N, 0); //一共2^N个状态
        vector > city(N, vector()); //记录城市的先后顺序
        for(int i = 0; i < List.size(); i++)
            city[List[i].y - 1].push_back(List[i].x - 1);
        return search(city, dp, A, N, V, 0, 0);
    }
};

复杂度分析

时间复杂度:递归中需要循环的部分其实只有dp的大小,其他的都是直接返回

空间复杂度:dp占用空间,city最差情况下

算法思想二:状压dp

解题思路:

解题思路
1、状态定义:dp[i]表示二进制mask为i时,需要的旅游开销。
2、状态初始化:将mask为0设为起点,表示不去任何城市时,旅游开销是0。其他mask位设为无穷大,表示不可达。
3、状态转移:如果当前城市没有来过,并且当前城市i的前置城市都去过了,则可转移到下一个mask位,对应开销加上当前城市开销,即
当所有的mask位都统计完成后,计算满足开销不大于V的最大可去城市数目(mask位中1的个数)。

代码展示:

JAVA版本

import java.util.*;
/*
 * public class Point {
 *   int x;
 *   int y;
 *   public Point(int x, int y) {
 *     this.x = x;
 *     this.y = y;
 *   }
 * }
 */
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param N int整型 N
     * @param V int整型 V
     * @param A int整型一维数组 A
     * @param List Point类一维数组 List
     * @return int整型
     */
    public int Travel (int N, int V, int[] A, Point[] List) {
        // write code here
        //初始化限制数组
        int[][] limit=new int[N][N];
        for(Point p:List){
            limit[p.y-1][p.x-1]=1;
        }
        //初始化状态压缩dp,dp[i]表示二进制mask为i时,需要的旅游开销
        int[] dp=new int[1<<N];
        Arrays.fill(dp,Integer.MAX_VALUE/2);
        dp[0]=0;
        for(int mask=0;mask<(1<<N);mask++){
            //如果mask不可达,直接跳过
            if(dp[mask]==Integer.MAX_VALUE/2) continue;
            for(int i=0;i<N;i++){
                //如果当前城市已经来过,则跳过
                if(((mask>>i)&1)!=0) continue;
                //判断当前城市i是否还有未去过的前置城市
                boolean pass=true;
                for(int j=0;j<N;j++){
                    if(limit[i][j]==1&&((mask>>j)&1)==0){
                        pass=false;
                        break;
                    }
                }
                if(!pass) continue;
                //如果前置城市都去过了,则跳到下一个mask
                dp[mask|1<<i]=dp[mask]+A[i];
            }
        }

        int res=0;
        for(int mask=0;mask<(1<<N);mask++){
            //如果旅游开销不大于V,则计算对应的最大的可去城市数
            if(dp[mask]<=V){
                res=Math.max(res,Integer.bitCount(mask));
            }
        }
        return res;
    }
}

复杂度分析

时间复杂度:总共三层循环,第一层大小2^n,第二层和第三层大小都是n

空间复杂度:dp占用空间

全部评论

相关推荐

头像
04-25 18:51
已编辑
华东师范大学 算法工程师
暑期实习从2月开始投,面了两个月,流程该挂的都挂完了,腾讯字节一共号称是1.7w个hc,不知道都发给谁了,估计今年秋招要难顶。Timeline米哈游、美团、蚂蚁、微软等公司直接简历挂穿,没进面。携程:3.3&nbsp;投递、测评3.12&nbsp;笔试3.18&nbsp;一面3.25&nbsp;二面4.13&nbsp;ai面(hr面)4.14&nbsp;英语测评4.23&nbsp;offer(已拒)腾讯:2.6&nbsp;测评2.28&nbsp;wxg一面3.5&nbsp;wxg二面(挂)3.11&nbsp;teg一面3.21&nbsp;teg二面(取消)3.31&nbsp;teg一面4.10&nbsp;teg二面(挂)4.21&nbsp;wxg一面4.24&nbsp;wxg二面(挂)字节:1.28&nbsp;aml约面(取消)3.17&nbsp;火山一面(挂)4.8&nbsp;aml一面(挂)4.20&nbsp;抖音data一面(挂)阿里:3.23&nbsp;投递、测评3.28&nbsp;笔试3.31&nbsp;淘天一面4.8&nbsp;钉钉一面4.9&nbsp;淘天二面4.10&nbsp;阿里控股一面4.12&nbsp;钉钉二面(取消)4.15&nbsp;淘天hr面4.16&nbsp;淘天offer(已接)4.21&nbsp;高德一面(取消)4.22&nbsp;淘宝闪购一面(取消)面试最大的感触是,现在撞上ai转型,一堆老业务急着转向,新业务非常不成熟,研究型的组bar非常高根本进不去,业务侧挂着算法的岗位干的都是工程活,面试却又要问算法,另外agent的落地也远没有那么广,绝大多数还是那套写死的系统调一下llm&nbsp;api或者做做rag,其余少部分真的在搭agent的,基本不能在线上服务用什么很智能的模型,现阶段成本太高,进去大概率就是给垃圾模型从工程方面兜底,除了业务场景的应用和数据经验以外,技术方面很难有什么提升。算法岗做不了基模的还是去搜广推好,之前判断失误了完全没投,秋招不知道还进不进得去。
绿糖滑稽:携程这什么雷霆流程时长
我的求职进度条
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务