题意:在一个 6×6 的网格中,有一些车。车用一个长方形表示,满足只 有宽或长为 1。若宽为 1,则车左右移动,否则上下移动。 每辆车移动过程中不能有某个部分出现在另一辆车上。 在第 3 行第 6 列格子的右边有一个缺口,其他地方没有缺口。 除了 1 号车外,其他车子不能移出网格外。1 号车也只能从缺口处移出网格。 某个车每走一格算做一步。 问将 1 号车从缺口处移走的最少步数(车身完全移走),若步数 ≤ 10,则输出最小步数, 否则输出 −1。
思路://写过的最长的bfs,当然要记录一下 [汗.jpg]
没有技巧,就是硬bfs,用重载node的set记录状态是否到达过。
方法就是从初始状态开始进行bfs,每次扩展出来一个新状态(即让某一辆车移动一步),比较麻烦的点在于记录状态和判重。
这个题的每个状态应该是一个矩阵,代表这个状态的停车场分布。所以建一个struct存状态。
然后扩展新状态,就是枚举每辆车,使其上下/左右移动一步,若这个状态没出现过,就入队。
判重应该可以用hash或者set,我hash不太熟练,所以就用了set(重载一下"<“和”==")
然后我程序里,用了cars记录的每辆车的位置和状态(水平or竖直),为了方便移动车子。 node是用来存每个状态。
变量说明:
cars中,len是车子长度、u记录车子在同一列还是是同一行、pos存车子所在的列/行、s和t记录车头车尾的位置。
node中,step是使用的步数、v[20]存每个车子现在的位置、a存停车场矩阵
(好像要素有点多,如果有更容易的写法当然更好)
#include<bits/stdc++.h>
using namespace std;
int a_[7][7],ans=11,cnt=1,c,sum;
struct cars{
int len;
int u,pos,s,t; //u=1行,u=0列
cars(){u=-1;s=7;}
}v[20];
struct node{
int step;
cars v[20];
int a[7][7];
int c;
node(){
for(int i=0;i<=6;i++)
for(int j=0;j<=6;j++)a[i][j]=0;
}
bool operator <(const node &o)const{
bool flag=1;
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++)if(a[i][j]<o.a[i][j]){flag=0;break;}
if(!flag)break;
}
return flag;
}
bool operator ==(const node &o)const{
bool flag=1;
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++)if(a[i][j]!=o.a[i][j]){flag=0;break;}
if(!flag)break;
}
return flag;
}
};
set<node>st;
typedef set<node>::iterator IT;
void init(){
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)cin>>a_[i][j];
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)if(a_[i][j]&&v[a_[i][j]].u==-1){
int t=a_[i][j];
if(a_[i-1][j]==a_[i][j]||a_[i+1][j]==a_[i][j]){
v[t].u=0;
v[t].pos=j;
for(int k=1;k<=6;k++)if(a_[k][j]==t){
v[t].s=min(v[t].s,k);
v[t].t=max(v[t].t,k);
v[t].len++;
}
}else{
v[t].u=1;
v[t].pos=i;
for(int k=1;k<=6;k++)if(a_[i][k]==t){
v[t].s=min(v[t].s,k);
v[t].t=max(v[t].t,k);
v[t].len++;
}
}
cnt=max(cnt,t);
}
sum=7-v[1].s;
}
queue<node>q;
void bfs(){
node now,nxt;
IT it;
int pos;
for(int i=1;i<=cnt;i++)now.v[i]=v[i];
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)now.a[i][j]=a_[i][j];
now.step=0;
q.push(now);
st.insert(now);
while(!q.empty()){
nxt=now=q.front();q.pop();
int flag=1;
for(int i=now.v[1].t+1;i<=6;i++)if(now.a[3][i])flag=0;
if(flag){
ans=sum+now.step;
return;
}
if(sum+now.step==11)break;
if(sum+now.step==10)continue;
for(int k=1;k<=cnt;k++){
pos=v[k].pos;
for(int i=now.v[k].s-1;i<=now.v[k].s-1&&i>=1;i++){
if(v[k].u==1){//位于同一行
if(now.a[pos][i])continue;
nxt.step++;
swap(nxt.a[pos][i],nxt.a[pos][now.v[k].t]);
nxt.v[k].s--;
nxt.v[k].t--;
it=st.lower_bound(nxt);
if(it!=st.end()&&!(*it==nxt)){
q.push(nxt);
st.insert(nxt);
}
nxt.step--;
swap(nxt.a[pos][i],nxt.a[pos][now.v[k].t]);
nxt.v[k].s++;
nxt.v[k].t++;
}else{//位于同一列
if(now.a[i][pos])continue;
nxt.step++;
swap(nxt.a[i][pos],nxt.a[now.v[k].t][pos]);
nxt.v[k].s--;
nxt.v[k].t--;
it=st.lower_bound(nxt);
if(it!=st.end()&&!(*it==nxt)){
q.push(nxt);
st.insert(nxt);
}
nxt.step--;
swap(nxt.a[i][pos],nxt.a[now.v[k].t][pos]);
nxt.v[k].s++;
nxt.v[k].t++;
}
}
for(int i=now.v[k].t+1;i<=now.v[k].t+1&&i<=6;i++){
if(v[k].u==1){//位于同一行
if(now.a[pos][i])continue;
nxt.step++;
swap(nxt.a[pos][i],nxt.a[pos][now.v[k].s]);
nxt.v[k].s++;
nxt.v[k].t++;
it=st.lower_bound(nxt);
if(it!=st.end()&&!(*it==nxt)){
q.push(nxt);
st.insert(nxt);
}
nxt.step--;
swap(nxt.a[pos][i],nxt.a[pos][now.v[k].s]);
nxt.v[k].s--;
nxt.v[k].t--;
}else{//位于同一列
if(now.a[i][pos])continue;
nxt.step++;
swap(nxt.a[i][pos],nxt.a[now.v[k].s][pos]);
nxt.v[k].s++;
nxt.v[k].t++;
it=st.lower_bound(nxt);
if(it!=st.end()&&!(*it==nxt)){
q.push(nxt);
st.insert(nxt);
}
nxt.step--;
swap(nxt.a[i][pos],nxt.a[now.v[k].s][pos]);
nxt.v[k].s--;
nxt.v[k].t--;
}
}
}
}
}
int main(){
init();
bfs();
if(ans>10)ans=-1;
cout<<ans;
}