The Clocks(DFS)

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 according 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个数,每个数都只可能由3,6,9,12四个数字组成,代表时间。9个数由顺序A到 I 9个字母表示。题中给出9种选择方法,每种方法都有一串字母,代表要转动该字母位置上的钟,每次最多只能转90度。问如何选择方法来使全部钟都能为12。最后输出该方法数序列,若多个满足,则输出字典序最小的。

 

    思路:

    DFS。方案数一共有4^9种,一个钟最多只能转4次。一开始将点数定义为0,1,2,3来方便计算。  

    有两点必须清楚:

    1.每种方法不止用一次,可以用多次;

    2.每个钟都可以用多次,但事实上一个钟最多只能转4次,因为当转完4次后就回到了原来的位置了;最终生成的方法数序列与每种方法选的顺序无关。

 

    AC:

    

/*
TASK:clocks
LANG:C++
ID:sum-g1
*/

#include<stdio.h>
#include<string.h>

typedef struct
{
    int p[4][4];
}node;
node way[10];
int map[4][4],time[10];
int fin[50],num[50],minans=50,temp=0;

void init()
{
    memset(way,0,sizeof(way));
    memset(time,0,sizeof(time));
    way[1].p[1][1]=way[1].p[1][2]=way[1].p[2][1]=way[1].p[2][2]=1;
    way[2].p[1][1]=way[2].p[1][2]=way[2].p[1][3]=1;
    way[3].p[1][2]=way[3].p[1][3]=way[3].p[2][2]=way[3].p[2][3]=1;
    way[4].p[1][1]=way[4].p[2][1]=way[4].p[3][1]=1;
    way[5].p[1][2]=way[5].p[2][1]=way[5].p[2][2]=way[5].p[2][3]=way[5].p[3][2]=1;
    way[6].p[1][3]=way[6].p[2][3]=way[6].p[3][3]=1;
    way[7].p[2][1]=way[7].p[2][2]=way[7].p[3][1]=way[7].p[3][2]=1;
    way[8].p[3][1]=way[8].p[3][2]=way[8].p[3][3]=1;
    way[9].p[2][2]=way[9].p[2][3]=way[9].p[3][2]=way[9].p[3][3]=1;
}

int check()
{
    int res=1;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        if(map[i][j]!=0)
        {
            res=0;
            break;
        }
    return res;
}

void dfs(int w,int ans)
{
    num[ans]=w;
    time[w]++;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        map[i][j]=(map[i][j]+way[w].p[i][j])%4;

    if(ans>=minans||time[w]>3)      return;   //WA在这里,time[w]>3时应该是return
//但是一开始把time[w]>3放在数组中了,并且判断的时候是time[w]>3时是continue
//最后导致前面会输出很多多余的数
    if(check())
    {
        minans=ans;
        for(int i=1;i<=minans;i++) fin[i]=num[i];
    }

    for(int k=num[ans];k<=9;k++)
    {
        if(!k)        continue;
        dfs(k,ans+1);
        for(int o=1;o<=3;o++)
            for(int j=1;j<=3;j++)
            map[o][j]=(map[o][j]+4-way[k].p[o][j])%4;
        time[k]--;
    }
}

int main()
{
    freopen("clocks.in","r",stdin);
    freopen("clocks.out","w",stdout); 
    init();
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        {
            scanf("%d",&map[i][j]);
            if(map[i][j]==3)  map[i][j]=1;
            if(map[i][j]==6)  map[i][j]=2;
            if(map[i][j]==9)  map[i][j]=3;
            if(map[i][j]==12) map[i][j]=0;
        }
    dfs(0,0);
    for(int i=1;i<=minans;i++)
    {
        printf("%d",fin[i]);
        i==minans?printf("\n"):printf(" ");
    }
    return 0;
}

 

    总结:

    1.首先是读题问题,一开始读错了两次,写了两遍错误的代码。第一次单纯只因为没有完全理解题意,第二次是读懂了,但是以为每种方法最多只允许用1次;

    2.写dfs时候的思维还是略混乱,更新clock语句应放在哪里,判断return的语句又应放在哪里,return之后哪些变量要更新回原来状态,这些都要一一考虑清楚;

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值