USACO1.4.2

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.

MoveAffected clocks
1ABDE
2ABC
3BCEF
4ADG
5BDEFH
6CFI
7DEGH
8GHI
9EFHI

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坑死了,整整坑了两天。仅仅因为把赋值符号“=”打成“==”了,然后就一直不输出结果,惨痛的教训啊,以后一定要记住!!!
View Code
 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:

View 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 }

 




<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值