解决从某一状态到另一状态,状态很大
1.八数码https://www.acwing.com/problem/content/181/
问最少步数将 23415x768 -> 12345678x.九宫格移动,x为空格
#include<unordered_map>
#define PII pair<int,int>
const int N = 1e3 + 50;
typedef pair<int,string>PIS;
int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
string st,ed,seq;
int f(string x) {
int res=0;
for(int i=0; i<x.length(); i++) {
if(x[i] != ‘x‘) {
int t = x[i] - ‘1‘;
res += abs(i/3-t/3)+abs(i%3-t%3);
}
}
return res;
}
string bfs(string st) {
ed = "12345678x";
char op[10]="urdl";
unordered_map<string,int>dist;//状态对应的步数
//某状态前一状态和对应的走法
unordered_map<string,pair<char,string> >pre;
//队列:{估价函数,状态}
priority_queue<PIS,vector<PIS>,greater<PIS> >q;
dist[st]=0;
q.push({f(st),st});
while(q.size()) {
PIS now = q.top();
q.pop();
string state = now.second;
if(state == ed)break;
int x,y;
for(int i=0; i<9; i++) { //找到x的位置
if(state[i] == ‘x‘) {
x=i/3,y=i%3;
break;
}
}
string temp = state;
for(int i=0; i<4; i++) {
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx<0||nx>=3||ny<0||ny>=3)continue;
state = temp; //初始状态
swap(state[x*3+y],state[nx*3+ny]);
if(dist.count(state)==0 || dist[state] > dist[temp] + 1) {
dist[state] = dist[temp] + 1;
pre[state] = {op[i],temp};
q.push({dist[state]+f(state),state});
}
}
}
string ans;
while(ed != st) {
ans += pre[ed].first;
ed = pre[ed].second;
}
reverse(ans.begin(),ans.end());
return ans;
}
void work() {
char c;
while(cin >> c) {
st += c;
if(c!=‘x‘)seq += c;
}
int cnt=0;
for(int i=0; i<8; i++) {
for(int j=i+1; j<8; j++) {
if(seq[i]>seq[j])cnt++;
}
}
if(cnt&1)printf("unsolvable\n");
else cout << bfs(st) << endl;
}
2.https://www.acwing.com/problem/content/180/
k短路:反向用dijk求出每个点到ed的最短距离,用它作为估价函数,再正向求ed第k次出队时的distance;
#define fi first
#define se second
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int N = 1e3 + 50,M = 2e5 + 50;
int n,m,st,ed,k;
int h[N],rh[N],e[M],ne[M],w[M],idx;
int dist[N];
int vis[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 dijk() {
priority_queue<PII,vector<PII>,greater<PII> >q;
q.push({0,ed});
memset(dist,0x3f,sizeof(dist));
dist[ed] = 0;
while(q.size()) {
PII now = q.top();
q.pop();
int ver = now.se;
if(vis[ver])continue;
vis[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];
q.push({dist[j],j});
}
}
}
}
int astar() {
priority_queue<PIII,vector<PIII>,greater<PIII> >q;
//{评估函数,{到st的距离,当前点}}
q.push({dist[st],{0,st}});
int cnt =0;
while(q.size()) {
PIII now = q.top();
q.pop();
int ver = now.se.se;
int distance = now.se.fi;
if(ver == ed)cnt++;
if(cnt == k)return distance;
for(int i=h[ver]; ~i; i=ne[i]) {
int j = e[i];
q.push({distance+w[i]+dist[j],{distance+w[i],j}});
}
}
return -1;
}
void work() {
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
memset(rh,-1,sizeof(rh));
while(m--) {
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",&st,&ed,&k);
if(st == ed)k++;
dijk();
if(dist[st] == 0x3f3f3f3f)printf("-1\n");
else printf("%d\n",astar());
}