poj 1166 The Clocks

枚举+位运算
//题意是有9个时钟,输入用0、1、2、3分别代表3、6、9、12点,有9种不同的操作,都是让某些时钟沿顺时针方向转90°。
//问题是求最少的步骤使得所有时钟都指向12点
//思路:让一个数表示9个钟面的状态,从小到大枚举操作步骤

#include<iostream> //枚举+位运算
#include<string>
using namespace std;
string Move[9]={"ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI"};
int fac[9]={1,8,64,512,4096,32768,262144,2097152,16777216} ;
long mod=0333333333; //以0作为八进制数的前缀
// mod=( 011 011 011 011 011 011 011 011 011 ),对应于九个位置,状态值有4种可能:0,1,2,3
// 通过与操作 t = t & mod ; 可以对九个位置的状态值 % 4

int main()
{
int num=0,p,mv[10]; //mv[i]=c表示重复第i+1 种移动方式 c次
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
{
scanf("%d",&p);
num+= p * fac[i*3+j]; //初始状态num
}
//暴力穷举,搜索空间为:4^9=262144
for(mv[0]=0;mv[0]<4;++mv[0]) //枚举移动0-3次,因为4次相当于没有移动
for(mv[1]=0;mv[1]<4;++mv[1])
for(mv[2]=0;mv[2]<4;++mv[2])
for(mv[3]=0;mv[3]<4;++mv[3])
for(mv[4]=0;mv[4]<4;++mv[4])
for(mv[5]=0;mv[5]<4;++mv[5])
for(mv[6]=0;mv[6]<4;++mv[6])
for(mv[7]=0;mv[7]<4;++mv[7])
for(mv[8]=0;mv[8]<4;++mv[8])
{
int t=num;
for(int i=0;i<9;++i) //9种移动方法
{
for(int j=0;j<mv[i];++j) //重复移动mv[i]次
for(int k=0;k<Move[i].length();++k) //移动哪个时钟
{
t += fac[Move[i][k]-'A']; //对该位置(Move[i][k]-'A')的状态值 +1
t = t & mod ; //相当于对九个位置的状态值 % 4

}
}
if(t==0) //0表示九个位置的时钟都指向了12点
{
for(int i=0;i<9;++i)
for(int j=0;j<mv[i];++j)
cout<<i+1<<" ";
cout<<endl;
return 0;
}
}
}

 

 

BFS+位运算
#include<iostream>        // BFS+位运算
#include<string>
using namespace std;
string Move[9]={"ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI"};
int fac[9]={1,8,64,512,4096,32768,262144,2097152,16777216} ;
const int mod=0333333333; //以0作为八进制数的前缀
// mod=( 011 011 011 011 011 011 011 011 011 ),对应于九个位置,状态值有4种可能:0,1,2,3
// 通过与操作 t = t & mod ; 可以对九个位置的状态值 % 4
const int maxn=1<<18; // 4^9
int q[maxn],path[maxn],fa[maxn],ans[maxn];
int vis[mod];

void bfs(int x)
{
q[0]=x;
fa[0]=0;
vis[x]=1;
int front=0,rear=1;
while(front<rear)
{
if(q[front]==0)
{
int u=front,r=0;
while(u>0)
{
ans[r++]=path[u];
u=fa[u];
}
for(int i=r-1;i>=0;--i) //打印路径
printf("%d ",ans[i]);
printf("\n");
break;
}
for(int i=0;i<9;++i) //9种移动方法
{
int t=q[front];
for(int j=0;j<Move[i].length();++j) //移动哪个时钟
{

t += fac[Move[i][j]-'A']; //对该位置(Move[i][k]-'A')的状态值 +1
t = t & mod ; //相当于对九个位置的状态值 % 4
}
if(!vis[t]) //判重
{
vis[t]=1;
fa[rear]=front;
path[rear]=i+1;
q[rear++]=t;
}
}
front++;
}
}
int main()
{
int x=0,p;
for(int i=0;i<3;++i)
{
for(int j=0;j<3;++j)
{
scanf("%d",&p);
x+= p * fac[i*3+j]; //初始状态x
}
}
bfs(x);
return 0;
}



posted on 2011-07-06 15:57  sysu_mjc  阅读(315)  评论(0编辑  收藏  举报

导航