您的位置:首页 > 其它

UVa 12112 - Iceman

2015-11-02 19:49 405 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  暴搜 uva