双向广搜
可以将指数级别的时间复杂度降低到线性 优化效果很好
一般用于最小步数模型
#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的算法
#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;
}
#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;
}