USACO1.4.4

The Clocks
IOI'94 - Day 2

Consider nine clocks arranged in a 3x3 array thusly: 

|-------|    |-------|    |-------|    

|       |    |       |    |   |   |    

|---O   |    |---O   |    |   O   |          

|       |    |       |    |       |           

|-------|    |-------|    |-------|    

    A            B            C

|-------|    |-------|    |-------|

|       |    |       |    |       |

|   O   |    |   O   |    |   O   |

|   |   |    |   |   |    |   |   |

|-------|    |-------|    |-------|

    D            E            F

|-------|    |-------|    |-------|

|       |    |       |    |       |

|   O   |    |   O---|    |   O   |

|   |   |    |       |    |   |   |

|-------|    |-------|    |-------|

    G            H            I

The goal is to find a minimal sequence of moves to return all the dials to 12 o'clock. Nine different ways to turn the dials on the clocks are supplied via a table below; each way is called a move. Select for each move a number 1 through 9 which will cause the dials of the affected clocks (see next table) to be turned 90 degrees clockwise.

Move

Affected clocks

1

ABDE

2

ABC

3

BCEF

4

ADG

5

BDEFH

6

CFI

7

DEGH

8

GHI

9

EFHI

Example

Each number represents a time accoring to following table: 

9 9 12       9 12 12       9 12 12        12 12 12      12 12 12 

6 6 6  5 ->  9  9  9  8->  9  9  9  4 ->  12  9  9  9-> 12 12 12 

6 3 6        6  6  6       9  9  9        12  9  9      12 12 12 

[But this might or might not be the `correct' answer; see below.]

PROGRAM NAME: clocks

INPUT FORMAT

Lines 1-3:

Three lines of three space-separated numbers; each number represents the start time of one clock, 3, 6, 9, or 12. The ordering of the numbers corresponds to the first example above.

SAMPLE INPUT (file clocks.in)

9 9 12

6 6 6

6 3 6

OUTPUT FORMAT

A single line that contains a space separated list of the shortest sequence of moves (designated by numbers) which returns all the clocks to 12:00. If there is more than one solution, print the one which gives the lowest number when the moves are concatenated (e.g., 5 2 4 6 < 9 3 1 1).

SAMPLE OUTPUT (file clocks.out)

4 5 8 9

在每个状态下,其下一次旋转有9种选择,每种选择得到一个新的状态,由此,可以想到由广搜(BFS),将每次得到的不同的状态(以前没有得到)压入队列,直到搜到需要的结果,因为要输出操作步骤,在此用了两个数组,一个数组用来记录路径,一个用来记录相应路径对应的步骤。还有一个很重要的问题,就是每个状态怎样存储,时钟只有3,6,9,12;我们不妨都除以3,得到1,2,3,4;在对4取余,得到0,1,2,3,每个钟上的数字对应一位四进制数,将每个状态所对应的四进制的数转换成十进制的数,所需数组大小为4^9不会MLE。具体代码如下:

/*
ID:jinyuxu2
LANG:C++
PROG:clocks
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int x,len;
int ans[200];
int vis[270000];
int p[270000];
int a[9],b[9];
int map[9]={65536,16384,4096,1024,256,64,16,4,1};
queue<int>q;
int vis_Next(int v)
{
 if(v==1)
 {
 a[0]=(a[0]+1)%4;
 a[1]=(a[1]+1)%4;
 a[3]=(a[3]+1)%4;
 a[4]=(a[4]+1)%4;
 }
 if(v==2)
 {
 a[0]=(a[0]+1)%4;
 a[1]=(a[1]+1)%4;
 a[2]=(a[2]+1)%4;
 }
 if(v==3)
 {
 a[1]=(a[1]+1)%4;
 a[2]=(a[2]+1)%4;
 a[4]=(a[4]+1)%4;
 a[5]=(a[5]+1)%4;
 }
 if(v==4)
 {
 a[0]=(a[0]+1)%4;
 a[3]=(a[3]+1)%4;
 a[6]=(a[6]+1)%4;
 }
 if(v==5)
 {
 a[1]=(a[1]+1)%4;
 a[3]=(a[3]+1)%4;
 a[4]=(a[4]+1)%4;
 a[5]=(a[5]+1)%4;
 a[7]=(a[7]+1)%4;
 }
 if(v==6)
 {
 a[2]=(a[2]+1)%4;
 a[5]=(a[5]+1)%4;
 a[8]=(a[8]+1)%4;
 }
 if(v==7)
 {
 a[3]=(a[3]+1)%4;
 a[4]=(a[4]+1)%4;
 a[6]=(a[6]+1)%4;
 a[7]=(a[7]+1)%4;
 }
 if(v==8)
 {
 a[6]=(a[6]+1)%4;
 a[7]=(a[7]+1)%4;
 a[8]=(a[8]+1)%4;
 }
 if(v==9)
 {
 a[4]=(a[4]+1)%4;
 a[5]=(a[5]+1)%4;
 a[7]=(a[7]+1)%4;
 a[8]=(a[8]+1)%4;
 }
 int sum=0;
 for(int i=0;i<9;i++)
 sum+=a[i]*map[i];
 return sum;
}
void BFS()
{
 while(!q.empty())
 {
 int t=q.front();
 q.pop();
 if(t==0)
 break;
 for(int i=0;i<9;i++)
 b[i]=(t/map[i])%4;
 for(int i=1;i<10;i++)
 {
 for(int j=0;j<9;j++)
 a[j]=b[j];
 int cnt=vis_Next(i);
 if(vis[cnt]==-1)
 {
 p[cnt]=i;
 vis[cnt]=t;
 q.push(cnt);
 }
 }
 }
}
int main()
{
 freopen("clocks.in","r",stdin);
 freopen("clocks.out","w",stdout);
 int w;
 x=0;
 len=0;
 for(int i=0;i<9;i++)
 {
 scanf("%d",&w);
 w/=3;
 w%=4;
 x+=w*map[i];
 }
 memset(vis,-1,sizeof(vis));
 memset(p,-1,sizeof(p));
 q.push(x);
 BFS();
 int i=0;
 while(vis[i]!=x)
 {
 ans[len++]=p[i];
 i=vis[i];
 }
 ans[len]=p[i];
 for(int i=len;i>0;i--)
 printf("%d ",ans[i]);
 printf("%d\n",ans[0]);
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值