算法思想一:暴力法
解题思路:
对于求解本题牛妹最多能到多少个城市去旅游,我们可以直接模拟牛妹的访问过程,首先我们定义city,dp,flag数组,分别记录城市之间的次序关系,每个城市的前序访问和该城市有无被访问过。然后我们开始进行模拟访问,首先没有前序城市的城市进入队列,每次花费最小或者下标最小的城市出队,然后将相邻的后续城市的前序数量减一。最后我们可以遍历完所有城市,并且根据花费,计算出牛妹最多可以到达多少个城市去旅游。
整个过程使用了拓扑排序的思想
图解:
代码展示:
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整型
*/
struct node{
int val;
int index;
bool friend operator < (node a, node b) // 根据本题目重载小于号
{ //花费优先,然后是下标
if(a.val == b.val)
return a.index > b.index;
return a.val > b.val;
}
};
int Travel(int N, int V, vector<int>& A, vector<Point>& list) {
// write code here
vector dp(N + 1, 0); // 记录有多少个前序城市
int res = 0; // 声明结果
vector > city(N + 1, vector ()); // 记录城市之间的次序
for(int i = 0; i < list.size(); i++)
{
city[list[i].x].push_back(list[i].y); // 城市入队
dp[list[i].y]++;
}
priority_queue q;
vector flag(N + 1, false); // 声明flag数组来记录该城市是否被访问
for(int i = 1; i <= N; i++)
{
if(dp[i] == 0)
{
q.push({A[i - 1], i}); // 没有前序的城市可以直接放入队列,优先访问花费最小的
flag[i] = true; // 记录访问过该点
}
}
while(!q.empty())
{
node temp = q.top();
q.pop();
if(temp.val > V) // 预算不够了
break;
V -= temp.val;
res++;
for(int i = 0; i < city[temp.index].size(); i++) // 该城市的所有后序城市的前序数量减一
dp[city[temp.index][i]]--;
for(int i = 1; i <= N; i++)
{ //遍历每个城市,如果该城市的前序为0且没有被访问过
if(dp[i] == 0 && !flag[i])
{
q.push({A[i - 1], i});
flag[i] = true;
}
}
}
return res; // 返回结果
}
}; 复杂度分析
时间复杂度:两层循环加一个队列时间
空间复杂度:使用额外数组,因此空间复杂度为
算法思想二:方法一优化
解题思路:
基于方法一,发现每次dp数组中的元素归零时,它一定还没有被访问过,同时它又只能收到前序城市的影响,因此可以将其直接加入队列中,从而省去flag数组,继而对代码进行优化。
图解(流程和方法一是一样的):
代码展示:
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整型
*/
struct node{
int val;
int index;
bool friend operator < (node a, node b) // 根据本题目重载小于号
{ //花费优先,然后是下标
if(a.val == b.val)
return a.index > b.index;
return a.val > b.val;
}
};
int Travel(int N, int V, vector<int>& A, vector<Point>& list) {
// write code here
vector dp(N + 1, 0); // 记录有多少个前序城市
int res = 0; // 记录结果
vector > city(N + 1, vector ()); //记录城市之间的次序
for(int i = 0; i < list.size(); i++)
{
city[list[i].x].push_back(list[i].y); // 对城市进行判断
dp[list[i].y]++;
}
priority_queue q;
for(int i = 1; i <= N; i++)
if(dp[i] == 0)
q.push({A[i - 1], i});
while(!q.empty())
{
node temp = q.top();
q.pop();
if(temp.val > V) // 预算不够了
break;
V -= temp.val;
res++;
for(int i = 0; i < city[temp.index].size(); i++)
{ //该城市的所有后序城市的前序数量减一
dp[city[temp.index][i]]--;
if(dp[city[temp.index][i]] == 0) // 刚刚为0的城市一定还没有被访问过
q.push({A[city[temp.index][i] - 1], city[temp.index][i]});
}
}
return res; // 返回结果
}
}; 复杂度分析
时间复杂度:两层循环加一个队列时间
空间复杂度:使用额外数组,因此空间复杂度为



京公网安备 11010502036488号