当前位置: 首页 > news >正文

A* floyd算法 bellman-ford

求源点到目标点最短距离

排序的里面要加上与目标点一个预估距离,与dj算法差距只有这儿

预估要小于等于真实的最短距离,吸引力要适当

越接近实际距离越快

#include<bits/stdc++.h>
using namespace std;

// 方向向量:上、右、下、左
const vector<int> directions = {-1, 0, 1, 0, -1};

struct Node {
    int x, y, cost;
    bool operator>(const Node &other) const {
        return cost > other.cost;
    }
};

// Dijkstra 算法
int minDistance1(vector<vector<int>> &grid, int startX, int startY, int targetX, int targetY) {
    if (grid[startX][startY] == 0 || grid[targetX][targetY] == 0) return -1;
    
    int n = grid.size(), m = grid[0].size();
    vector<vector<int>> distance(n, vector<int>(m, INT_MAX));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    priority_queue<Node, vector<Node>, greater<Node>> heap;
    
    distance[startX][startY] = 1;
    heap.push({startX, startY, 1});
    
    while (!heap.empty()) {
        Node cur = heap.top(); heap.pop();
        int x = cur.x, y = cur.y;
        
        if (visited[x][y]) continue;
        visited[x][y] = true;
        
        if (x == targetX && y == targetY) return distance[x][y];
        
        for (int i = 0; i < 4; ++i) {
            int nx = x + directions[i], ny = y + directions[i + 1];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == 1 && !visited[nx][ny] && distance[x][y] + 1 < distance[nx][ny]) {
                distance[nx][ny] = distance[x][y] + 1;
                heap.push({nx, ny, distance[nx][ny]});
            }
        }
    }
    return -1;
}

// 曼哈顿距离
int heuristic(int x, int y, int targetX, int targetY) {
    return abs(targetX - x) + abs(targetY - y);
}

// A* 算法
int minDistance2(vector<vector<int>> &grid, int startX, int startY, int targetX, int targetY) {
    if (grid[startX][startY] == 0 || grid[targetX][targetY] == 0) return -1;
    
    int n = grid.size(), m = grid[0].size();
    vector<vector<int>> distance(n, vector<int>(m, INT_MAX));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    priority_queue<Node, vector<Node>, greater<Node>> heap;
    
    distance[startX][startY] = 1;
    heap.push({startX, startY, 1 + heuristic(startX, startY, targetX, targetY)});
    
    while (!heap.empty()) {
        Node cur = heap.top(); heap.pop();
        int x = cur.x, y = cur.y;
        
        if (visited[x][y]) continue;
        visited[x][y] = true;
        
        if (x == targetX && y == targetY) return distance[x][y];
        
        for (int i = 0; i < 4; ++i) {
            int nx = x + directions[i], ny = y + directions[i + 1];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] == 1 && !visited[nx][ny] && distance[x][y] + 1 < distance[nx][ny]) {
                distance[nx][ny] = distance[x][y] + 1;
                heap.push({nx, ny, distance[x][y] + 1 + heuristic(nx, ny, targetX, targetY)});
            }
        }
    }
    return -1;
}

// 生成随机地图
vector<vector<int>> randomGrid(int n) {
    vector<vector<int>> grid(n, vector<int>(n, 1));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if ((double)rand() / RAND_MAX < 0.3) {
                grid[i][j] = 0; // 30% 概率为障碍
            }
        }
    }
    return grid;
}

int main() {
    srand(time(0));
    int len = 100, testTime = 10000;
    cout << "功能测试开始" << endl;
    for (int i = 0; i < testTime; ++i) {
        int n = rand() % len + 2;
        vector<vector<int>> grid = randomGrid(n);
        int startX = rand() % n, startY = rand() % n;
        int targetX = rand() % n, targetY = rand() % n;
        int ans1 = minDistance1(grid, startX, startY, targetX, targetY);
        int ans2 = minDistance2(grid, startX, startY, targetX, targetY);
        if (ans1 != ans2) {
            cout << "出错了!" << endl;
        }
    }
    cout << "功能测试结束" << endl;
    
    cout << "性能测试开始" << endl;
    vector<vector<int>> grid = randomGrid(4000);
    int startX = 0, startY = 0, targetX = 3900, targetY = 3900;
    clock_t start, end;
    
    start = clock();
    int ans1 = minDistance1(grid, startX, startY, targetX, targetY);
    end = clock();
    cout << "运行 Dijkstra 算法结果: " << ans1 << ", 运行时间(毫秒): " << (end - start) * 1000.0 / CLOCKS_PER_SEC << endl;
    
    start = clock();
    int ans2 = minDistance2(grid, startX, startY, targetX, targetY);
    end = clock();
    cout << "运行 A* 算法结果: " << ans2 << ", 运行时间(毫秒): " << (end - start) * 1000.0 / CLOCKS_PER_SEC << endl;
    
    cout << "性能测试结束" << endl;
    return 0;
}

floyd任意两点最短,不能有负环,可以有负边,距离就会变成无穷负

中间点最先枚举跳板点,看能不能缩短距离

P2910 [USACO08OPEN] Clear And Present Danger S - 洛谷

#include <bits/stdc++.h>
using namespace std;
const int maxn=101;
const int maxm=10001;
int path[maxm];
int distance1[maxn][maxn];//点 
int n,m,ans;
void floyd()
{
	for(int bridge=1;bridge<=n;bridge++)
	{
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			if(distance1[i][bridge]!=INT_MAX&&distance1[bridge][j]!=INT_MAX&&distance1[i][j]>distance1[i][bridge]+distance1[bridge][j])
			distance1[i][j]=distance1[i][bridge]+distance1[bridge][j];
		}
	}
}
int main()
{
   cin>>n>>m;
   for(int i=0;i<m;i++) 
   cin>>path[i];
   for(int i=1;i<=n;i++)
   for(int j=1;j<=n;j++)
   distance1[i][j]=INT_MAX;
   for(int i=1;i<=n;i++)
   for(int j=1;j<=n;j++)
   cin>>distance1[i][j];
   floyd();
   int ans=0;
   for(int i=1;i<m;i++)
   ans+=distance1[path[i-1]][path[i]];
   cout<<ans;
}

bellman-ford可以解决单源最短路问题,比dj算法强在可以解决负边

787. K 站中转内最便宜的航班 - 力扣(LeetCode)

流程就是每次遍历每一条边,看看能不能缩小某两点距离,进行n-1轮操作后,一定可以松弛所有边的距离

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
    vector<int> cur(n,INT_MAX),nxt;
    cur[src]=0;
    //限制不超过k+1条边
    for(int i=0;i<=k;i++)
    {
       nxt=cur;
       for(auto a:flights)
       {
          if(cur[a[0]]!=INT_MAX)
          nxt[a[1]]=min(nxt[a[1]],cur[a[0]]+a[2]);
       }
       cur=nxt;
    }
    return cur[dst]==INT_MAX?-1:cur[dst];
    }
};

判断是否存在负环时候也可以用

SPFA优化

就是哪条点动过了就在下一轮优化

P3385 【模板】负环 - 洛谷

#include<bits/stdc++.h>
using namespace std;
const int maxn=2001;
const int maxm=6001;
int head[maxn],n,m;
int nxt[maxm];
int to[maxm];
int weight[maxm],cnt=1;
int distance1[maxn];
int updatecnt[maxn];//标记一个点被松弛次数
bool enter[maxn];
queue<int>q;
void addedge(int u,int v,int w)
{
	nxt[cnt]=head[u];
	to[cnt]=v;
	weight[cnt]=w;
	head[u]=cnt++;
}
bool spfa()
{
	distance1[1]=0;
	updatecnt[1]++;
	q.push(1);
	enter[1]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		enter[u]=false;
		for(int ei=head[u],v,w;ei>0;ei=nxt[ei])
		{
			v=to[ei];
			w=weight[ei];
			if(distance1[u]+w<distance1[v])
			{
				distance1[v]=distance1[u]+w;
				if(!enter[v])
				{
					if(++updatecnt[v]>n-1)
					return true;
					q.push(v);
					enter[v]=true;
				}
			}
		}
	}
	return false;
}
int main() 
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		fill(distance1+1,distance1+n+1,INT_MAX);
	    while(!q.empty()) q.pop();
	    cnt=1;
		memset(updatecnt,0,sizeof(updatecnt));
		memset(enter,0,sizeof(enter));
		memset(head,0,sizeof(head));
		for(int i=1,u,v,w;i<=m;i++)
		{
			cin>>u>>v>>w;
			if(w>=0)
			{
				addedge(u,v,w);
				addedge(v,u,w);
			}
			else
			addedge(u,v,w);
		}
		cout<<(spfa()?"YES":"NO")<<endl;
	} 
}

没有优化过的版本 

#include<bits/stdc++.h>
using namespace std;
const int maxn=2001;
const int maxm=6001;
int head[maxn],n,m;
int nxt[maxm];
int to[maxm];
int weight[maxm],cnt=1;
int distance1[maxn];
void addedge(int u,int v,int w)
{
	nxt[cnt]=head[u];
	to[cnt]=v;
	weight[cnt]=w;
	head[u]=cnt++;
}
bool spfa()
{
	distance1[1]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			//遍历每一条边
			for(int k=head[j];k>0;k=nxt[k])
			{
				if(distance1[j]!=INT_MAX&&distance1[to[k]]>distance1[j]+weight[k])
				{
					if(i==n)
					return true;
					distance1[to[k]]=distance1[j]+weight[k];
				}
			}
		}
	}
	return false;
}
int main() 
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		fill(distance1+1,distance1+n+1,INT_MAX);
	    cnt=1;
		memset(head,0,sizeof(head));
		for(int i=1,u,v,w;i<=m;i++)
		{
			cin>>u>>v>>w;
			if(w>=0)
			{
				addedge(u,v,w);
				addedge(v,u,w);
			}
			else
			addedge(u,v,w);
		}
		cout<<(spfa()?"YES":"NO")<<endl;
	} 
}

相关文章:

  • 使用傅里叶变换测量声卡的频率失真
  • DeepSeek提示词高级指南:正反向组合的工程化实践
  • 【人工智能】【Python】在Scikit-Learn中使用网格搜索对决策树调参
  • 不同路径
  • Linux项目自动化构建工具-make/Makefile
  • 兴达易控modbus协议转换网关配置步骤
  • 【华为OD-E卷 -121 消消乐游戏 100分(python、java、c++、js、c)】
  • 用Python打造智能姓名生成器:从数据分离到AI赋能
  • CMake 保姆级教程
  • opencv初步学习——图像处理2
  • AI Agent--李宏毅
  • 【数学建模】一致矩阵的应用及其在层次分析法(AHP)中的性质
  • Python yield 解析:原理、示例与 send 方法
  • 一周热点:法官在人工智能训练版权案中支持版权主张
  • Anaconda conda常用命令:从入门到精通
  • unserialize3 [有难度,序列化反序列化知识点]
  • 网络编程基础
  • 239.滑动窗口的最大值
  • Power Apps 技术分享:连接SharePoint列表数据源
  • AI大模型完全指南:从核心原理到行业落地实践
  • 什么样的公司需要做网站/免费crm客户管理系统
  • 网站域名怎么解释/百度搜索排名查询
  • b2c商城网站源码/手机如何制作网站
  • 做本地网站应该选什么内容/中国营销策划第一人
  • 深圳网站制作价格/企业网站营销的典型案例
  • 自己网站做短链接/徐州网站建设