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
解题思路:DFS。每种方案最多选三次,因为旋转四次就恢复原状态了,相当于没进行操作。由于方案的顺序并不重要,因此满足要求就可以输出,中断搜索。
表示被一个BUG坑死了,整整坑了两天。仅仅因为把赋值符号“=”打成“==”了,然后就一直不输出结果,惨痛的教训啊,以后一定要记住!!!
1 /* 2 ID:spcjv51 3 PROG:clocks 4 LANG:C 5 */ 6 #include<stdio.h> 7 #include<stdlib.h> 8 #define MAXSTEPS 30 9 const int a[9][9]= 10 { 11 {1,1,0,1,1,0,0,0,0}, 12 {1,1,1,0,0,0,0,0,0}, 13 {0,1,1,0,1,1,0,0,0}, 14 {1,0,0,1,0,0,1,0,0}, 15 {0,1,0,1,1,1,0,1,0}, 16 {0,0,1,0,0,1,0,0,1}, 17 {0,0,0,1,1,0,1,1,0}, 18 {0,0,0,0,0,0,1,1,1}, 19 {0,0,0,0,1,1,0,1,1}, 20 }; 21 int now[9],minstep; 22 int path[MAXSTEPS],time[9]; 23 int init() 24 { 25 int i,k; 26 for(i=0; i<9; i++) 27 { 28 scanf("%d",&k);; 29 now[i]=(k/3)%4; 30 } 31 memset(path,0,sizeof(path)); 32 memset(time,0,sizeof(time)); 33 } 34 int ok() 35 { 36 int i; 37 for(i=0; i<9; i++) 38 if(now[i]%4!=0)return 0; 39 return 1; 40 } 41 void output() 42 { 43 int i; 44 for(i=0;i<minstep-1;i++) 45 printf("%d ",path[i]+1); 46 printf("%d\n",path[minstep-1]+1); 47 48 } 49 50 51 void change(int i) 52 { 53 int j; 54 for(j=0; j<9; j++) 55 now[j]+=a[i][j]; 56 } 57 void regain(int i) 58 { 59 int j; 60 for(j=0; j<9; j++) 61 now[j]-=a[i][j]; 62 63 } 64 void search(int step) 65 { 66 int i,j; 67 if(step>=MAXSTEPS) return; 68 if(ok()) 69 { 70 minstep=step; 71 output(); 72 return; 73 } 74 if (step==0) j=0; 75 else if(time[path[step-1]]<3) j=path[step-1]; 76 else 77 j=path[step-1]+1; 78 for(i=j; i<9; i++) 79 { 80 change(i); 81 time[i]++; 82 path[step]=i; 83 search(step+1); 84 regain(i); 85 time[i]--; 86 87 } 88 } 89 90 int main(void) 91 { 92 freopen("clocks.in","r",stdin); 93 freopen("clocks.out","w",stdout); 94 init(); 95 search(0); 96 return 0; 97 }
USACO上的题解真是太犀利了,好简短。
You can precalculate a matrix a as following:
a[i][0],a[i][1],....,a[i][8] is the number of moves '1','2','3',...'9' necessarly to move ONLY clock i (where 0 < i <= 8 - there are 9 clocks: 0=A, 1=B, ... 8=I) 90 degrees clockwise. So, you have the matrix:
int a[9][9]= { {3,3,3,3,3,2,3,2,0}, {2,3,2,3,2,3,1,0,1}, {3,3,3,2,3,3,0,2,3}, {2,3,1,3,2,0,2,3,1}, {2,3,2,3,1,3,2,3,2}, {1,3,2,0,2,3,1,3,2}, {3,2,0,3,3,2,3,3,3}, {1,0,1,3,2,3,2,3,2}, {0,2,3,2,3,3,3,3,3} };
That means: to move ONLY the clock 0 (clock A) 90 degrees clockwise you have to do {3,3,3,3,3,2,3,2,0}, 3 moves of type 1, three moves of type 2, ..., 2 moves of type 8, 0 moves of type 9, etc.
To move ONLY the clock 8 (clock I), you have to do the moves {0,2,3,2,3,3,3,3,3}: 0 moves of type 1, 2 moves of type 2... 3 moves of type 9....
That's it! You count in a vector v[9] how many moves of each type you have to do, and the results will be modulo 4 (%4 - 5 moves of any type have the same effect 1 move has). The source code:
1 #include <stdio.h> 2 3 int a[9][9]= { {3,3,3,3,3,2,3,2,0}, 4 {2,3,2,3,2,3,1,0,1}, 5 {3,3,3,2,3,3,0,2,3}, 6 {2,3,1,3,2,0,2,3,1}, 7 {2,3,2,3,1,3,2,3,2}, 8 {1,3,2,0,2,3,1,3,2}, 9 {3,2,0,3,3,2,3,3,3}, 10 {1,0,1,3,2,3,2,3,2}, 11 {0,2,3,2,3,3,3,3,3} }; 12 int v[9]; 13 14 int main() { 15 int i,j,k; 16 freopen("clocks.in","r",stdin); 17 for (i=0; i<9; i++) { 18 scanf("%d",&k); 19 for(j=0; j<9; j++) 20 v[j]=(v[j]+(4-k/3)*a[i][j])%4; 21 } 22 fclose(stdin); 23 24 k=0; 25 freopen("clocks.out","w",stdout); 26 for (i=0; i<9; i++) 27 for (j=0; j<v[i]; j++) 28 if (!k) { printf("%d",i+1); k=1; } 29 else printf(" %d",i+1); 30 printf("\n"); 31 fclose(stdout); 32 return 0; 33 }