您的位置:首页 > 其它

【USACO】时钟(BFS)

2018-03-26 21:32 204 查看

题目描述

考虑将如此安排在一个 3 x3 行列中的九个时钟:|-------| |-------| |-------|
| | | | | | |
|---O | |---O | | O |
| | | | | |
|-------| |-------| |-------|
A B C
|-------| |-------| |-------|
| | | | | |
| O | | O | | O |
| | | | | | | | |
|-------| |-------| |-------|
D E F
|-------| |-------| |-------|
| | | | | |
| O | | O---| | O |
| | | | | | | |
|-------| |-------| |-------|
G H I目标要找一个最小的移动顺序次将所有的指针指向12点。下面原表格列出了9种不同的旋转指针的方法,每一种方法都叫一次移动。选择1到9号移动方法,将会使在表格中对应的时钟的指针顺时针旋转90度。移动方法 受影响的时钟
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
Example

9 9 12 9 12 12 9 12 12 12 12 12 12 12 126 6 6 5 -> 9 9 9 8-> 9 9 9 4 -> 12 9 9 9-> 12 12 126 3 6 6 6 6 9 9 9 12 9 9 12 12 12 [但这可能不是正确的方法,请看下面]

输入

第1-3行: 三个空格分开的数字,每个数字表示一个时钟的初始时间,3,6,9,12。数字的含意和上面第一个例子一样。

输出

单独的一行包括一个用空格分开的将所有指针指向12:00的最短移动顺序的列表。 如果有多种方案,输出那种使的连接起来数字最小的方案。(举例来说5 2 4 6 < 9 3 1 1)。

样例输入

9 9 12
6 6 6
6 3 6

样例输出

4 5 8 9

提示

思路:很明显的BFS,用ans数组记录一下方法,用pre数组记录一下到当前点的路径,判断某个状态是否已经出现过,即vis过,转化成4进制的9位数,因为只有4种状态,则可用数组存下了。最后递归输出就好了。

代码:#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>

using namespace std;

#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)

const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const int N = 1e7+5;

int vis
;
int b[10];
int pre
;
int ans
;
int res;

int dir[10][10]={
0,0,0,0,0,0,0,0,0,0,
0,1,1,0,1,1,0,0,0,0,
0,1,1,1,0,0,0,0,0,0,
0,0,1,1,0,1,1,0,0,0,
0,1,0,0,1,0,0,1,0,0,
0,0,1,0,1,1,1,0,1,0,
0,0,0,1,0,0,1,0,0,1,
0,0,0,0,1,1,0,1,1,0,
0,0,0,0,0,0,0,1,1,1,
0,0,0,0,0,1,1,0,1,1
};

int cal(int a[])
{
int sum=0;
int tmp=1;
for(int i=1;i<=9;i++)
{
sum+=a[i]*tmp;
tmp*=4;
}
return sum;
}

struct node
{
int a[10];
int idx; //索引
};

void bfs()
{
queue<node>q;
node now,next;
MEM(vis,0);
int x=cal(b);
vis[x]=1;
for(int i=1;i<=9;i++)
now.a[i]=b[i];
int cnt=0;
now.idx=0;
pre[now.idx]=-1;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
bool flag=true;
for(int i=1;i<=9;i++)
if(now.a[i]!=3)
flag=false;
if(flag)
{
res=now.idx;
return;
}
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)

4000
next.a[j]=(now.a[j]+dir[i][j])%4;
int tmp=cal(next.a);
if(!vis[tmp])
{
cnt++;
vis[tmp]=1;
next.idx=cnt;
pre[next.idx]=now.idx;
ans[next.idx]=i;
q.push(next);
}
}
}
}

void output(int xx)
{
if(pre[xx]==-1)
{
return ;
}
output(pre[xx]);
printf("%d ",ans[xx]);
}

int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
std::ios::sync_with_stdio(false);
int n;
while(~scanf("%d",&b[1]))
{
for(int i=2;i<=9;i++)
scanf("%d",&b[i]);
bool flag=true;
for(int i=1;i<=9;i++)
{
b[i]=b[i]/3-1;
if(b[i]!=3)
flag=false;
}
if(flag)
{
printf("\n");
continue;
}
bfs();
output(pre[res]);
printf("%d\n",ans[res]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USACO BFS