A*star算法:
在bfs问题中,所有边权都是非负的,那么就可以使用启发函数来优化bfs过程。
特征:点数非常多
虽然bfs里没有剪枝操作,但是A*算法通过它独有的贪心,来做出一些预测,尽可能的使操作缩短。
思路:首先把起点到终点的最短距离当作估值函数,因为无论其他怎么走到终点,都会使得路径长度>=最短距离。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define PIII pair<int,PII>
const int N = 1010;
const int M = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int n,m,S,T,K;
int h[N],rh[N],e[M],w[M],ne[M],idx;
int dist[N],cnt[N];
int 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 dijstra()
{
priority_queue<PII,vector<PII>,greater<PII> > heap;
memset(dist,0x3f,sizeof dist);
dist[T] = 0;
heap.push({0,T});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second;
if(st[ver]) continue;
st[ver] = true;
for(int i = rh[ver]; ~i; i = ne[i])
{
int j = e[i];
if(dist[j] > dist[ver] + w[i])
{
dist[j] = dist[ver] + w[i];
heap.push({dist[j],j});
}
}
}
}
//我这里这个DIJ,意义是算最短路,S ----> K -----> T的K到T的值,因为把K -----> T是估值函数,(这样就没有比他更优的了且非常接近真实值)
int astar()
{
priority_queue<PIII,vector<PIII>,greater<PIII> >heap;
heap.push({dist[S],{0,S}});//估计值,真实值,点在哪
//谁的d[u] + f[u] 为什么最优,因为真实值只会比他 >=
//我要再去找S ----> K
while(heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second.second,distance = t.second.first;
cnt[ver] ++;
//cout << cnt[T] << endl;
if(cnt[T] == K) return distance;
for(int i = h[ver]; ~i; i = ne[i])
{
int j = e[i];
if(cnt[j] < K)
{
heap.push({distance + w[i] + dist[j],{distance + w[i],j}});
//d[u] + c + f[j]
}
}
}
return -1;
}
void solve()
{
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 ++;
dijstra();
printf("%d\n",astar());
}
int main()
{
solve();
system("pause");
return 0;
}
思路:
小结论:奇数码有解条件-------逆序对的数量必须是偶数
估值函数:每个点与目标距离的曼哈顿距离
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, string>
#define PIS pair<char, string>
const int N = 1e6 + 10;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;
string str,ed,start;
unordered_map<string,int>dist;
unordered_map<string,PIS>pre;
int hr[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int f(string s)
{
int res = 0;
for(int i = 0; i < 9; i ++)
if(s[i] != 'x')
{
int t = s[i] - '1';
res += abs(t / 3 - i / 3) + abs(t % 3 - i % 3);
}
return res;
}
void bfs(string start,string ed)
{
priority_queue<PII,vector<PII>,greater<PII> > heap;
dist[start] = 0;
heap.push({f(start),start});
char op[5] = {"urdl"};//对应的是坐标下的
while(heap.size())
{
auto t = heap.top();
heap.pop();
string state = t.second;
if(state == ed) break;
int qwq = state.find('x');
int x = qwq / 3;
int y = qwq % 3;
string source = state;
for(int i = 0; i < 4; i ++)
{
int a = x + hr[i][0];
int b = y + hr[i][1];
if(a < 0 || a >= 3 || b < 0 || b >= 3) continue;
state = source;
swap(state[x * 3 + y],state[a * 3 + b]);
if(!dist.count(state) || dist[state] > dist[source] + 1)
{
dist[state] = dist[source] + 1;
pre[state] = {op[i],source};
heap.push({dist[state] + f(state),state});
}
}
}
}
bool flag(string seq)
{
//cout << seq << endl;
int sum = 0;
for(int i = 0; i < 8; i ++)
for(int j = i + 1; j < 8; j ++)
{
if(seq[i] > seq[j]) sum ++;
}
if(sum % 2)
{
puts("unsolvable");
return true;
}
return false;
}
void solve()
{
getline(cin,str);
string seq;
for(int i = 0; i < str.size(); i ++)
{
if(str[i] != ' ') start += str[i];
if(str[i] != ' ' && str[i] != 'x') seq += str[i];
}
if(flag(seq)) return;
ed = "12345678x";
bfs(start,ed);
string res;
while(start != ed)
{
res += pre[ed].first;
ed = pre[ed].second;
}
reverse(res.begin(),res.end());
cout << res << endl;
}
int main()
{
solve();
system("pause");
return 0;
}