双向广搜 and A*

双向广搜

可以将指数级别的时间复杂度降低到线性 优化效果很好

一般用于最小步数模型

1.字串变换

#include <bits/stdc++.h>
using namespace std;
const int N=6;
string a[N],b[N];
int n;
int extend(queue<string>& q,unordered_map<string,int>& da,unordered_map<string,int>& db,string a[],string b[])
{
    string t=q.front();
    q.pop();
    for(int i=0;i<t.size();i++)
    {
        for(int j=0;j<n;j++)
        {
            if(t.substr(i,a[j].size())==a[j])
            {
                string state=t.substr(0,i)+b[j]+t.substr(i+a[j].size());
                if(db.count(state)) return da[t]+1+db[state];
                if(da.count(state)) continue;
                da[state]=da[t]+1;
                q.push(state);
            }
        }
    }
    return 11;
}
int bfs(string A,string B)
{
    if(A==B) return 0;
    queue<string> qa,qb;
    unordered_map<string,int> da,db;
    qa.push(A),da[A]=0;
    qb.push(B),db[B]=0;
    while(qa.size()&&qb.size())
    {
        int t;
        if(qa.size()<=qb.size())
            t=extend(qa,da,db,a,b);
        else t=extend(qb,db,da,b,a);
        if(t<=10) return t;
    }
    return 11;//大于10的数
}
int main()
{
    string A,B;
    cin>>A>>B;
    while(cin>>a[n]>>b[n]) n++;
    int step=bfs(A,B);
    if(step>10) puts("NO ANSWER!");
    else printf("%d\n",step);
    return 0;
}

A*

A star 有启发函数

A star可以使用的条件是 估计距离小于等于真实距离并且一定要有解

Astar只能保证终点的距离是最小的,不能保证中间的所有点的距离是最小的(最多保证最优解的路径上的点是最小值)

A star可以用于没有负权回路的图上

A star主要的处理问题也是最小步数模型

而dijkstra是看成一种估价函数为0的算法

1.八数码

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,string> PIS;
int f(string state)
{
    int res=0;
    for(int i=0;i<state.size();i++)
    {
        if(state[i]!='x')
        {
            int t=state[i]-'1';
            res+=abs(i/3-t/3)+abs(i%3-t%3);
        }
    }
    return res;
}
string bfs(string start)
{
    string ed="12345678x";
    char op[]="urdl";
    unordered_map<string,int> dis;
    unordered_map<string,pair<char,string> > prev;
    priority_queue<PIS,vector<PIS>,greater<PIS> > heap;
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    dis[start]=0;
    heap.push({f(start),start});
    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        string state=t.y;
        if(state==ed)
            break;
        int x,y;
        for(int i=0;i<9;i++)
        {
            if(state[i]=='x')
            {
                x=i/3,y=i%3;
            }
        }
        string source=state;
        for(int i=0;i<4;i++)
        {
            int a=x+dx[i],b=y+dy[i];
            if(a<0||a>=3||b<0||b>=3)
                continue;
            state=source;
            swap(state[x*3+y],state[a*3+b]);
            if(dis.count(state)==0||dis[state]>dis[source]+1)
            {
                dis[state]=dis[source]+1;
                prev[state]={op[i],source};
                heap.push({dis[state]+f(state),state});
            }
        }
    }
    string res;
    while(ed!=start)
    {
        res+=prev[ed].x;
        ed=prev[ed].y;
    }
    reverse(res.begin(),res.end());
    return res;
}
int main()
{
    string start,seq;
    char c;
    while(cin>>c)
    {
        start+=c;
        if(c!='x') seq+=c;
    }
    int cnt=0;
    for(int i=0;i<8;i++)
        for(int j=i;j<8;j++)
        {
            if(seq[i]>seq[j])
                cnt++;
        }
    if(cnt&1) puts("unsolvable");
    else cout<<bfs(start)<<endl;
    return 0;
}

2.第k短路

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int N=1010,M=200010;
int n,m,S,T,K;
int h[N],rh[N],e[M],ne[M],w[M],idx;
int dis[N];
bool st[N];
void add(int h[],int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dijkstra()
{
    priority_queue<PII,vector<PII>,greater<PII>> heap;
    heap.push({0,T});
    memset(dis,0x3f,sizeof dis);
    dis[T]=0;
    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        int ver=t.y;
        if(st[ver]) continue;
        st[ver]=true;
        for(int i=rh[ver];~i;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[ver]+w[i])
            {
                dis[j]=dis[ver]+w[i];
                heap.push({dis[j],j});
            }
        }
    }
}
int astar()
{
    priority_queue<PIII,vector<PIII>,greater<PIII>> heap;
    heap.push({dis[S],{0,S}});
    int cnt=0;
    if(dis[S]==0x3f3f3f3f) return -1;
    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        int ver=t.y.y,distance=t.y.x;
        if(ver==T)
        {
            cnt++;
        }
        if(cnt==K) return distance;
        for(int i=h[ver];~i;i=ne[i])
        {
            int j=e[i];
            heap.push({distance+w[i]+dis[j],{distance+w[i],j}});
        }
    }
    return -1;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof h);
    memset(rh,-1,sizeof rh);
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(h,a,b,c);
        add(rh,b,a,c);
    }
    scanf("%d%d%d",&S,&T,&K);
    if(S==T) K++;
    dijkstra();
    printf("%d\n",astar());
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值