zoukankan      html  css  js  c++  java
  • 洛谷 P1312 Mayan游戏

    题目传送门

    大模拟,用的bfs,完全按照题目描述做即可,其实本题用dfs要更好写.

    我的做法有点缺陷,但是不知道在哪里,不开(O_2)优化会T一个点.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    
    using namespace std;
    
    int n,a[10][10],oi,f_step;
    string f_ans;//最后答案 
    map<string,int> p;//到当前状态的步数 
    map<string,bool> vis;//bfs用 
    map<string,string> ans;//到当前的状态的过程 
    queue<string> w;
    
    inline bool check(string l) {//检查是否到了全部消掉的状态 
    	for(int i = 0;i < l.length(); i++)
    		if(l[i] != '0') return 0;
    	return 1;
    }
    
    inline bool _compare(string l) {//更新答案 
    	string u = ans[l];
    	for(int i = 0;i < min(u.length(),f_ans.length()); i++) {
    		int s1,s2;
    		s1 = u[i] - '0';
    		s2 = f_ans[i] - '0';
    		if((i + 1) % 3 == 0) {
    			if(s1 > s2) return 1;
    			if(s1 < s2) return 0;
    		}
    		else {
    			if(s1 < s2) return 1;
    			if(s1 > s2) return 0;
    		}
    	}
    	return 1;
    }
    
    inline void update_answer(string l) {
    	if(_compare(l)) {
    		f_step = p[ans[l]];
    		f_ans = ans[l];
    	} 
    }
    
    inline string chuli(string l) {//移动方块后,处理能消除的块及让悬空的块落下去 
    	int s[10][10],len = -1;
    	bool flag[10][10],oo = 0;
    	memset(flag,0,sizeof(flag));
    	for(int i = 0;i <= 6; i++) {
    		for(int j = 0;j <= 4; j++) {
    			s[i][j] = l[++len] - '0';
    		}
    	}
    	while(true) {
    		memset(flag,0,sizeof(flag));
    		oo = 0;
    		for(int i = 0;i <= 6; i++) {
    			for(int j = 0;j <= 4; j++){
    				if(s[i][j] == 0)
    					continue;
    				else {
    					int pp = i;
    					while(true) {
    						if(s[pp-1][j] != 0) break;
    						if(pp == 0) break;
    						s[pp-1][j] = s[pp][j];
    						s[pp][j] = 0;
    						pp--;
    					}
    				}
    			}
    		}
    		for(int i = 0;i <= 6; i++) {
    			for(int j = 0;j <= 4; j++) {
    				if(s[i][j] == 0) continue;
    				if(s[i][j] == s[i][j+1] && s[i][j] == s[i][j+2] && s[i][j] != 0)
    					flag[i][j] = flag[i][1+j] = flag[i][j+2] = 1,oo = 1;
    				if(s[i][j] == s[i+1][j] && s[i][j] == s[i+2][j] && s[i][j] != 0)
    					flag[i][j] = flag[i+1][j] = flag[i+2][j] = 1,oo = 1;
    			}
    		}
    		for(int i = 0;i <= 6; i++) {
    			for(int j = 0;j <= 4; j++)
    				if(flag[i][j])
    					s[i][j] = 0;
    		}
    		if(oo == 0) break;	
    	}
    	len = -1;
    	for(int i = 0;i <= 6; i++)
    		for(int j = 0;j <= 4; j++)
    			l[++len] = char(s[i][j] + 48);
    	return l;
    }
    
    inline string bj(string x1,string x2) {//只有在当前走的答案比已知的答案最优才会更新(最优性剪枝) 
    	for(int i = 0;i < min(x1.length(),x2.length()); i++) {
    		int s1,s2;
    		s1 = x1[i] - '0';
    		s2 = x2[i] - '0';
    		if((i + 1) % 3 == 0) {
    			if(s1 > s2) return x1;
    			if(s1 < s2) return x2;
    		}
    		else {
    			if(s1 < s2) return x1;
    			if(s1 > s2) return x2;
    		}
    	}
    	return x2;
    }
    
    inline void bfs() {
    	while(!w.empty()) {
    		string u = w.front();
    		w.pop();
    		vis[u] = 0;
    		if(p[u] >= n + 1) continue;
    		for(int i = 0;i < 35; i++) {
    			int x = i / 5;
    			int y = i % 5;
    			int step = p[u];
    			if(u[i] == '0') continue;
    			for(int k = 1;k >= -1; k -= 2) {
    				string l = u;
    				if(y == 4 && k == 1) continue;
    				if(y == 0 && k == -1) continue;
    				if(k == 1 && l[i] == l[i+1]) continue;
    				if(k == -1 && l[i-1] != '0') continue;
    				char o = l[i];
    				l[i] = l[i+k];
    				l[i+k] = o;
    				l = chuli(l);
    				string pp = ans[u];
    				pp = pp + char(y+48) + char(x+48) + char(k+48);
    				if(p[l] >= step + 1 || p[l] == 0) {//只有在步数更优的情况下才会更新ans 
    					if(ans.count(l)) ans[l] = bj(pp,ans[l]);
    					else ans[l] = pp;
    				}
    				string aa = ans[l];
    				if(check(l)) {
    					oi = 1;
    					update_answer(l);
    				}
    				if(!vis[l] && _compare(l)) {
    					vis[l] = 1;
    					p[l] = p[u] + 1;
    					w.push(l);
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d",&n);
    	string l;
    	for(int i = 0;i <= 4; i++)
    		for(int j = 0;j <= 20; j++) {
    			scanf("%d",&a[j][i]);
    			if(a[j][i] == 0) break;
    		}
    	for(int i = 0;i <= 6; i++) {
    		for(int j = 0;j <= 4; j++) {
    			char u = char(a[i][j] + 48);
    			l = l + u;
    		}
    	}
    	f_ans = "g";
    	p[l] = 1;
    	vis[l] = 1;
    	w.push(l);
    	bfs();
    	if(oi == 0) printf("-1");
    	else {
    		for(int i = 0;i < f_ans.length(); i++) {
    			if(f_ans[i] == '/')
    				cout << "-1";
    			else cout << f_ans[i] << ' ';
    			if(i % 3 == 2) cout << endl;
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    Golang 开发环境安装和配置
    多测师肖老师__接口测试之cms搭建(27.1)
    多测师肖老师__接口测试之fn+f12查看接口(27.2)
    认识wpf中binding类型
    认识wpf的事件
    Jquery对象与Dom对象
    AS3编程中的两种常用事件
    SQL Server 系统表简介
    Winform中ComcoBox控件设置选定项
    wpf开篇入门
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/13860845.html
Copyright © 2011-2022 走看看