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
这一题很明显可以用宽搜解决(后来看别人的解题报告才知道深搜也可以)
宽搜的话,就需要队列维护,并且要记录方案,这里记录方案的时候理论上可以用string和数组记录,但是频繁使用string,程序就变得异常的慢!所以后来改成了数组记录,并且宽搜的空间是很宝贵的,所以记录方案的数组开合适就可以了,我开的50,如果100的话Usaco就会提示错误(还是英文的,看了好久才明白)
hash的设计可以用stl的set或者自己设计hash均可
当然,这一题宽搜是可以剪枝的!由于题目钟表的特殊性,不管哪个方案,用4次就相当于没用,所以当当前方案在到4次的时候就可以剪枝了
Usaco对格式很苛刻就不用说了,不能有多余空格,要有一个回车
C++ Code
/*
ID: jiangzh15
TASK: clocks
LANG: C++
http://oijzh.cnblogs.com
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<string>
#include<queue>
using namespace std;
const int kkk[]={1,1,4,16,64,256,1024,4096,16384,65536};//hash表中要用
const int ddd[10][10]={ //A B C D E F G H I
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,0,1,1,0,0,0,0},//1 ABDE
{0,1,1,1,0,0,0,0,0,0},//2 ABC
{0,0,1,1,0,1,1,0,0,0},//3 BCEF
{0,1,0,0,1,0,0,1,0,0},//4 ADG
{0,0,1,0,1,1,1,0,1,0},//5 BDEFH
{0,0,0,1,0,0,1,0,0,1},//6 CFI
{0,0,0,0,1,1,0,1,1,0},//7 DEGH
{0,0,0,0,0,0,0,1,1,1},//8 GHI
{0,0,0,0,0,1,1,0,1,1},//9 EFHI
};
struct node{int a[10],step,c[50],way[10];};
queue<node> q;
node first;
bool h[262143+100];
int gethash(node x)
{
int sum=0;
for(int i=1;i<=9;i++)
sum+=x.a[i]*kkk[i];
return sum;
}
void check(node x)
{
for(int i=1;i<=9;i++)
if(x.a[i]!=0)return;
for(int i=1;i<=x.step-1;i++) printf("%d ",x.c[i]);
printf("%d\n",x.c[x.step]);
exit(0);
}
int main()
{
freopen("clocks.in","r",stdin);
freopen("clocks.out","w",stdout);
int i,j;
for(i=1;i<=9;i++)
{scanf("%d",&first.a[i]);first.a[i]=(first.a[i]%12)/3;}
first.step=0;
check(first);
q.push(first);
while(!q.empty())
{
node newnd,nd=q.front();q.pop();
//printf("%d\n",nd.step);
for(i=1;i<=9;i++)
{
if(nd.way[i]>=3)continue;
newnd=nd;
newnd.step++;
newnd.way[i]++;
for(j=1;j<=9;j++)
{
newnd.a[j]+=ddd[i][j];
if(newnd.a[j]>=4)newnd.a[j]-=4;
}
newnd.c[newnd.step]=i;
if(!h[gethash(newnd)])
{
/*printf("step=%d ",newnd.step);
for(int kk=1;kk<=newnd.step;kk++)
printf("%d ",newnd.c[kk]);
printf("\n");*/
check(newnd);
h[gethash(newnd)]=true;
q.push(newnd);
}
}
}
return 0;
}