【六月算法】D27 图的for (i = 0; i < s.size(); ++ i)搜索

搜索入门

搜索算法的原理就是枚举。利用 计算机的高性能,给出人类制定好的规则,枚举出所有可行的情况,找到可行解或者最优解。

搜索算法:

  • 深度优先搜索 

一般用来求可行解,利用剪枝(通过某种判断,避免一些不必要的搜索过程)进行优化,在树形结构的图上用处较多。

  • 广度优先搜索

一般用来求最优解,配合哈希表进行状态空间的标记,从而避免重复状态的计算。

深度优先搜索

一直往下走,走不通回头,还条路再走,直到无路可走;

具体算法:

选择一个起始点u作为当前节点,执行如下操作:

  1. 访问当前节点,并且标记当前节点已被访问,然后跳转到2;
  2. 如果存在一个和当前节点相邻并且未被访问的节点v,则将v设为当前节点,执行1;
  3. 如果不存在这样的节点v,则进行回溯,回溯过程就是回退当前节点。

算法实现:

可以用栈来存储当前节点,也可以用递归的方式来实现,以下是递归的方式;

const int MAXN = 7;

void dfs(int u) {
    if(visit[u]) {          //标记当前节点是否已被访问,被访问则返回,不被访问则访问,需自己实现的函数          
        return ;
    }
    visit[u] = true;                              
    dfs_add(u);            //存储当前节点 需自己实现的函数                              
    for(int i = 0; i < MAXN; ++i) {
        int v = i;
        if(adj[u][v]) {    //adj[u][v]为图的邻接矩阵,非0表示连通,0表示不连通                       
            dfs(v);                               
        }
    }
}

广度优先搜索

Breadth Fisrt Search,我会分身我怕谁?!

算法步骤:

  1. 选择一个起始点u放入一个先进先出的队列中,执行如下操作:
  2. 如果队列不为空,弹出一个队列首元素,记为当前接待您,执行3,否则算法结束;
  3. 将与当前节点相邻并且尚未被访问的节点的信息进行更新,并且全部放入队列中,继续执行2。

维护广搜的数据结构是队列和哈希表(标记状态),即open-close表。

广搜的最基础应用是用来求图的最短路。

算法实现:

const int inf = -1;

void bfs(int u) {
    queue <int> q;
    memset(dis, inf, sizeof(dis));               // 初始化路径数组,-1表示无限远
    dis[u] = 0;                        
    q.push(u);
    while(!q.empty()) {
        u = q.front();                           // 每次弹出一个元素
        q.pop();
        
        for(int v = 1; v <= n; ++v) {
            if(!adj[u][v]) continue;             // 不连通,跳过
            if(dis[v] != inf) continue;          // 节点已被访问过,跳过
            
            dis[v] = dis[u] + 1;                  
            q.push(v);                           //扩展下一个节点
        }
    }
}

相关题目

1514. 概率最大的路径

题目描述:

给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 a 和 b 的一条无向边,且该边遍历成功的概率为 succProb[i] 。

指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。

如果不存在从 start 到 end 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。

思路:

无向图的最长路问题,边权是概率,所以每次经过都是相乘的关系,由于概率是0-1的小数,所以会越乘越小,所以不存在环的情况;
直接用SPFA求解即可;

class Solution {
    #define maxn 10010
//碰到这种问题,首先要建边;
    struct Edge {
        int to;
        double val;
        Edge() {}
        Edge(int t, double v):to(t), val(v) {}
    };

    vector<Edge> edge[maxn];

    double bfs(int start, int end) {
        double dis[maxn];
        memset(dis, 0, sizeof(dis));

        queue<int> q;
        dis[start] = 1;
        q.push(start);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = 0; i < edge[u].size(); ++i) {
                int v = edge[u][i].to;
                double d = dis[u] * edge[u][i].val;
                if (d > dis[v]) { //利用概率为0-1之间的小数,越乘越小的特点
                    dis[v] = d;
                    q.push(v);
                }
            }
        }

        return dis[end];

    }
public:
    double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {

        for (int i = 0; i < succProb.size(); ++ i) {
            int u  = edges[i][0];
            int v = edges[i][1];
            double w = succProb[i];
            edge[u].push_back(Edge(v, w)); //有向图的处理
            edge[v].push_back(Edge(u, w));
            
        }

        return bfs(start, end);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import pandas as pd import numpy as np # 计算用户对歌曲的播放比例 triplet_dataset_sub_song_merged_sum_df = triplet_dataset_sub_song_mergedpd[['user', 'listen_count']].groupby('user').sum().reset_index() triplet_dataset_sub_song_merged_sum_df.rename(columns={'listen_count': 'total_listen_count'}, inplace=True) triplet_dataset_sub_song_merged = pd.merge(triplet_dataset_sub_song_mergedpd, triplet_dataset_sub_song_merged_sum_df) triplet_dataset_sub_song_mergedpd['fractional_play_count'] = triplet_dataset_sub_song_mergedpd['listen_count'] / triplet_dataset_sub_song_merged['total_listen_count'] # 将用户和歌曲编码为数字 small_set = triplet_dataset_sub_song_mergedpd user_codes = small_set.user.drop_duplicates().reset_index() song_codes = small_set.song.drop_duplicates().reset_index() user_codes.rename(columns={'index': 'user_index'}, inplace=True) song_codes.rename(columns={'index': 'song_index'}, inplace=True) song_codes['so_index_value'] = list(song_codes.index) user_codes['us_index_value'] = list(user_codes.index) small_set = pd.merge(small_set, song_codes, how='left') small_set = pd.merge(small_set, user_codes, how='left') # 将数据转换为稀疏矩阵形式 from scipy.sparse import coo_matrix mat_candidate = small_set[['us_index_value', 'so_index_value', 'fractional_play_count']] data_array = mat_candidate.fractional_play_count.values row_array = mat_candidate.us_index_value.values col_array = mat_candidate.so_index_value.values data_sparse = coo_matrix((data_array, (row_array, col_array)), dtype=float) # 使用SVD方法进行矩阵分解并进行推荐 from scipy.sparse import csc_matrix from scipy.sparse.linalg import svds import math as mt def compute_svd(urm, K): U, s, Vt = svds(urm, K) dim = (len(s), len(s)) S = np.zeros(dim, dtype=np.float32) for i in range(0, len(s)): S[i, i] = mt.sqrt(s[i]) U = csc_matrix(U, dtype=np.float32) S = csc_matrix(S, dtype=np.float32) Vt = csc_matrix(Vt, dtype=np.float32) return U, S, Vt def compute_estimated_matrix(urm, U, S, Vt, uTest, K, test): rightTerm = S * Vt max_recommendation = 250 estimatedRatings = np.zeros(shape=(MAX_UID, MAX_PID), dtype=np.float16) recomendRatings = np.zeros(shape=(MAX_UID, max_recommendation), dtype=np.float16) for userTest in uTest: prod = U[userTest, :] * rightTerm estimatedRatings[userTest, :] = prod.todense() recomendRatings[userTest, :] = (-estimatedRatings[userTest, :]).argsort()[:max_recommendation] return recomendRatings K = 50 urm = data_sparse MAX_PID = urm.shape[1] MAX_UID = urm.shape[0] U, S, Vt = compute_svd(urm, K) uTest = [4, 5, 6, 7, 8, 73, 23] # uTest=[1b5bb32767963cbc215d27a24fef1aa01e933025] uTest_recommended_items = compute_estimated_matrix(urm, U, S, Vt 继续将这段代码输出完整
最新发布
05-19

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值