A*bfs

解决从某一状态到另一状态,状态很大

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());
}
posted @ 2021-07-24 15:09  LaiYiC  阅读(35)  评论(0编辑  收藏  举报