UVa 12112 - Iceman

来源:互联网 发布:雄迈 监控软件密码 编辑:程序博客网 时间:2024/03/29 08:31

NOIP 临近 , 博主打算做搜索题..........


提示:

1. 本题理论上是不需要优化的 , 纯bfs就能搞定 , 所以建议大家大胆试一试

2. 白书上的h() 函数可以借鉴 , 博主的剪枝效果不大


注意: 有很多细节要注意 , 比如用魔法的时候 , 左右冰的状态一定会改变


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <algorithm>#include <queue>#include <set>#include <map>using namespace std;int n , m;int id(int a , int b) { return a*m+b; }struct state{string s;string op;int w , step;state(string s = " " , int w =0 , int step = 0):s(s),w(w),step(step){ op.clear(); }bool operator <(const state& b)const { return s<b.s || (s==b.s && w < b.w );  }};set<state> dic;int fall(string& s){for(int i=n-1;i>=0;i--) for(int j=0;j<m;j++){int L = id(i, j);if(s[L]=='@' || s[L]=='O'){int wh = L+m;while(wh<m*n && s[wh]=='.') wh+=m; wh-=m;if(L!=wh) swap(s[L], s[wh]); // note that wh might equal to L  , so swap is a good way to do the change}else if(s[L]=='[')for(int k=j+1;k<m;k++){int R = id(i, k);if(s[R]=='X') break;if(s[R]==']')  // from (i,j) to (i , k){int to = 0;for(int l=i+1;l<n;l++)  // check if (l , j) to (l , k) is empty{bool ok = true;for(int ii = j;ii<=k;ii++) if(s[id(l,ii)]!='.') { ok = false; break; }if(!ok) { to = l-1; break; }}if(to!=i) for(int l=j;l<=k;l++) swap(s[id(i,l)], s[id(to,l)]);j = k;break;}}}for(int i=0;i<s.size();i++) if(s[i]=='@') return i;return -1;}void linkRight(char& c){if(c==']') c = '=';else if(c=='O') c = '[';}void linkLeft(char& c){if(c=='[') c = '=';else if(c=='O') c = ']'; }bool solveMagic(state& s , int x , int y){int the = id(x, y);if(s.s[the]=='X') return false;if(s.s[the]=='.'){if(s.s[the-1]!='.' && s.s[the+1]!='.')  s.s[the] = '=' , linkRight(s.s[the-1]) , linkLeft(s.s[the+1]);  else if(s.s[the-1]!='.') s.s[the] = ']' , linkRight(s.s[the-1]); else if(s.s[the+1]!='.') s.s[the] = '[' , linkLeft(s.s[the+1]); else s.s[the] = 'O';}else{s.s[the] = '.';if(s.s[the-1]=='=') s.s[the-1] = ']';if(s.s[the-1]=='[') s.s[the-1] = 'O';if(s.s[the+1]=='=') s.s[the+1] = '[';if(s.s[the+1]==']') s.s[the+1] = 'O'; }s.w = fall(s.s);return true;}bool solveMove(state& s , int k){int the = s.w+k;if(s.s[the]=='.')swap(s.s[s.w], s.s[the]);else if(s.s[the]=='O' && s.s[the+k]=='.'){int wh = the;while(s.s[wh+k]=='.') { wh+=k; if(s.s[wh+m]=='.') break; }swap(s.s[the], s.s[wh]);}else if(s.s[the-m]=='.' && s.s[s.w-m]=='.')swap(s.s[s.w], s.s[the-m]);else return false;s.w = fall(s.s);return true;}void printnow(string s){cout<<endl;for(int i=0;i<n;i++) for(int j=0;j<m;j++) cout<<s[id(i, j)]<<(j==m-1?"\n":"");}int main(int argc, char *argv[]) {int Case=0;while(cin>>n&&n&&cin>>m){dic.clear();string s;char op;for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)  cin>>op , s = s+op;int S = 0 , T = 0 , tx , ty;for(int i=0;i<s.size();i++) if(s[i]=='@') S = i; else if(s[i]=='#') T = i , s[i]='.';tx = T/m; ty = T%m; queue<state> q;q.push(state(s , S , 0));cout<<"Case "<<++Case<<": ";while(!q.empty()){state now = q.front() , ne;q.pop();if(now.w==T) { cout<<now.op; break; }int x = now.w/m;int y = now.w%m;if(abs(y-ty)+now.step>15) continue;  ne = now;if(solveMagic(ne, x+1, y+1)){ne.op.push_back('>');ne.step++;if(dic.count(ne)==0) {dic.insert(ne);q.push(ne);}}ne = now;if(solveMagic(ne, x+1, y-1)){ne.op.push_back('<');ne.step++;if(dic.count(ne)==0) {dic.insert(ne);q.push(ne);}}ne = now;if(solveMove(ne, -1)){ne.op.push_back('L');if(dic.count(ne)==0) {dic.insert(ne);q.push(ne);}}ne = now;if(solveMove(ne, +1)){ne.op.push_back('R');if(dic.count(ne)==0) {dic.insert(ne);q.push(ne);}}}cout<<endl; }return 0;}


0 0
原创粉丝点击