• 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
    ");
    	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
    ");
    	else printf("%d
    ",astar());
    }
    
  • 相关阅读:
    hadoop安装前的准备
    记录一次Qt5程序无法运行的解决过程
    C#里的Thread.Join与Control.Invoke死锁情况
    qbxt7月笔记
    zhxのDP讲
    有n*m的方格图
    最长上升子序列相关问题笔记
    qbxt游记(清北澡堂划水记
    DAZの七下道法(持续更新
    模板
  • 原文地址:https://www.cnblogs.com/LaiYiC/p/15055260.html
Copyright © 2020-2023  润新知