搜索 POJ 3131 Cubic Eight-Puzzle
2016-09-03 20:57
387 查看
题目链接:POJ 3131 Cubic Eight-Puzzle
分析:
总是讨论空格,一共有四种可能,上下左右的方块可以滚过来。
对于一个格子,用pair记录两个值,xx表示上面的颜色,yy表示前面的颜色。
1=白色,2=红色,3=蓝色。
如果前后滚动,xx,yy交换。
如果左右滚动, yy不变,xx变成除了xx,yy之外的那一种颜色。
剪枝1: 记下上一层的空格在哪里,不要滚回去。
剪枝2: 最优化剪枝,看当前有几个格子和目标不一样,如果加上当前步数超过当前答案,则剪枝。
就这样水水的剪一剪就A了。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define xx first
#define yy second
#define LL long long
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))
#define INTpair pair<int,int>
using namespace std;
const int maxn=5,n=3,inf=32;
int ans,t[maxn][maxn];
INTpair s[maxn][maxn];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int Best(){
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(s[i][j].xx!=t[i][j]) ans++;
return ans;
}
void move(int x,int y,int type){
int x1=x+dx[type],y1=y+dy[type];
if(type<2)
swap(s[x][y].xx,s[x][y].yy);
else
s[x][y].xx=1^2^3^s[x][y].xx^s[x][y].yy;
swap(s[x][y],s[x1][y1]);
}
void DFS(int dep,int x,int y){
//x,y,是记录上一次的空格
int i,j,h=Best();
if(h==0){
ans=min(ans,dep);
return ;
}
if(dep+h>=ans) return ;
int x1,y1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(!s[i][j].xx)x1=i,y1=j;
//x1,t=y1,是现在空格的位置
for(i=0;i<4;i++){
int tx=dx[i]+x1,ty=dy[i]+y1;
if(tx>0&&tx<=n&&ty>0&&ty<=n&&(tx!=x||ty!=y)){
move(tx,ty,i^1);
DFS(dep+1,x1,y1);
move(x1,y1,i);
}
}
}
int main(){
int i,j,x,y;
char ch;
while(cin>>y>>x){
if(!y&&!x) return 0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)s[i][j]=make_pair(1,2);
s[x][y]=make_pair(0,0);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
cin>>ch;
if(ch=='E')t[i][j]=0;
else if(ch=='W')t[i][j]=1;
else if(ch=='R')t[i][j]=2;
else t[i][j]=3;
}
ans=inf;
DFS(0,0,0);
if(ans>30) ans=-1;
cout<<ans<<endl;
}
return 0;
}
分析:
总是讨论空格,一共有四种可能,上下左右的方块可以滚过来。
对于一个格子,用pair记录两个值,xx表示上面的颜色,yy表示前面的颜色。
1=白色,2=红色,3=蓝色。
如果前后滚动,xx,yy交换。
如果左右滚动, yy不变,xx变成除了xx,yy之外的那一种颜色。
剪枝1: 记下上一层的空格在哪里,不要滚回去。
剪枝2: 最优化剪枝,看当前有几个格子和目标不一样,如果加上当前步数超过当前答案,则剪枝。
就这样水水的剪一剪就A了。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define xx first
#define yy second
#define LL long long
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))
#define INTpair pair<int,int>
using namespace std;
const int maxn=5,n=3,inf=32;
int ans,t[maxn][maxn];
INTpair s[maxn][maxn];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int Best(){
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(s[i][j].xx!=t[i][j]) ans++;
return ans;
}
void move(int x,int y,int type){
int x1=x+dx[type],y1=y+dy[type];
if(type<2)
swap(s[x][y].xx,s[x][y].yy);
else
s[x][y].xx=1^2^3^s[x][y].xx^s[x][y].yy;
swap(s[x][y],s[x1][y1]);
}
void DFS(int dep,int x,int y){
//x,y,是记录上一次的空格
int i,j,h=Best();
if(h==0){
ans=min(ans,dep);
return ;
}
if(dep+h>=ans) return ;
int x1,y1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(!s[i][j].xx)x1=i,y1=j;
//x1,t=y1,是现在空格的位置
for(i=0;i<4;i++){
int tx=dx[i]+x1,ty=dy[i]+y1;
if(tx>0&&tx<=n&&ty>0&&ty<=n&&(tx!=x||ty!=y)){
move(tx,ty,i^1);
DFS(dep+1,x1,y1);
move(x1,y1,i);
}
}
}
int main(){
int i,j,x,y;
char ch;
while(cin>>y>>x){
if(!y&&!x) return 0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)s[i][j]=make_pair(1,2);
s[x][y]=make_pair(0,0);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
cin>>ch;
if(ch=='E')t[i][j]=0;
else if(ch=='W')t[i][j]=1;
else if(ch=='R')t[i][j]=2;
else t[i][j]=3;
}
ans=inf;
DFS(0,0,0);
if(ans>30) ans=-1;
cout<<ans<<endl;
}
return 0;
}
相关文章推荐
- img的间隙
- 结合Linux的应用场景看MIPS32架构之前言
- PHP endif、endwhile、endfor、冒号、switch、foreach使用介绍
- codeforces454CLittle Pony and Expected Maximum+数学期望
- codevs 1051 接龙游戏(栈模拟)
- Android 重要的文件目录和文件分析
- STL笔记之hashtable
- C++实现strcpy, strlen, strstr, atoi等字符串相关API
- ORACLE数据库的导入与导出,以及触发器的用法
- medsci
- 栈的压入、弹出序列
- CSRF (Cross Site Request Forgery)
- ios开发 UI高级 图形上下文
- 【oj进阶之路】各大oj题目分类,集合整理,各处转载
- ROS创建工作区域和功能包
- 数据离散化
- Qt Setting Application Icon
- sass实战演练03 - 响应式处理(1):变量模板、mixin实战用法
- 反转链表
- poj 2486 树形dp